dpcj32769
2015-04-29 14:49
浏览 520
已采纳

不能在laravel中使用控制器中的DB事务(DB :: beginTransaction)

I have a DoctorsController which has a store method. I'm testing this method and I want my Models not to INSERT their data in testing environment. So I'm using DB::beginTransaction , DB::rollback() , DB::commit() methods in my controllers and my testing method to prevent INSERT queries. my problem is => Database is having records while my tests are running. I don't want any INSERTS during tests.

My test code :

public function testStoreMethod()
{
    /*
     * Test when validation fails
     */
    $data = include_once('DoctorsControllerFormData.php');

    foreach($data as $item){
        DB::beginTransaction();
        $response = $this->call('POST', 'doctors', $item);
        $this->assertResponseStatus(400, "response's HTTP code is not 400 : " . implode('
',array_flatten($item)));
        Log::debug($response);
        DB::rollback();
    }
}

My DoctorsController code snippet : (which calls UsersController's store method)

public function store()
{
    //some code
    DB::beginTransaction();
    try{
        /*
         * User Creation
         */
        $user = new UsersController();
        $user->setResource('doctor');
        $userID = $user->store();

        //some other code
    }catch (InputValidationFailedException $e){
        DB::rollback();
        return Response::make(json_encode(array('error' => $e->getErrors())), \Symfony\Component\HttpFoundation\Response::HTTP_BAD_REQUEST);
    }catch(Exception $e){
        Log::error('Server Error at DoctorsController');
        DB::rollback();
        App::abort(500, $e->getMessage());
    }
}

My UsersController code snippet :

public function store()
{
    $user = new User;

    try{
        $inputs = Input::all();
        Log::info("input Data" . implode("
", array_flatten(Input::all())));
        /*
         * User Creation
         */
        $v = Validator::make(
            $inputs,
            User::$rules
        );

        if($v->fails()) {
            Log::error('Validation Failed! ' . implode("
", array_flatten($v->messages()->all())));
            throw new InputValidationFailedException($v);
        }
        $user->fname = Input::get('fname');//set first name
        $user->lname = Input::get('lname');//set last name
        $user->email = Input::get('email');//set email
        $user->cell = Input::get('cell');//set cell number
        $user->password = Hash::make(Input::get('password'));//set password
        $user->gender_id = Input::get('gender') == 'm' ? 1 : 0;//set gender
        $user->is_active = 0;//set activation status
        $user->role_id = ($this->resource == 'doctor') ? 1 : 2;
        $user->activation_time = 0;//set activation time default to 0
        $user->expiration_time = 0;//set expiration time default to 0
        //insert the user into DB
        $user->save();
    }catch (InputValidationFailedException $e){
        Log::info('User Validation Failed! ' . implode("
", array_flatten($e->getErrors())));
        throw $e;
    }catch (Exception $e){
        Log::error('Server Error at UsersController!');
        throw $e;
    }

    return $user->id;
}

Thanks for your help.

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

1条回答 默认 最新

  • douzong3599 2015-04-29 16:05
    最佳回答

    If you're commiting the changes in your controller, then the DB:rollback in your test can't undo those changes because the transaction was finished there. That being said, you shouldn't really be using the the same database for testing, as you are for development. Laravel has Migrations & Seeding which you can use to refresh and reseed a dedicated testing database any time you run your tests.

    If possible, I suggest using an in memory database to avoid writing to a persistent database altogether, as explained in the video linked below:

    Laracasts - Test DBs in Memory

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题