0

Im attempting to run a Laravel functional test, using the Model Factory to create some test data.

On other tests, within the same directory and namespace, using similar 'make' traits, no entries are saved in the database. But with this one they are.

When using app('env') it returns 'testing', so the environment is correct.

Any ideas on how I can run these tests without saving to the mySQL database?

RoleTest

namespace Tests;

use Tests\Traits\MakeRoleTrait;

class RoleTest extends BrowserKitTestCase
{
    use MakeRoleTrait;

    public function testGetChildren()
    {
        $childRoles = [];
        $baseRoles = [];

        for ($i = 0; $i < 4; $i++) {
            $parentId = null;

            if($i > 0){
                $parentId = $baseRoles[$i-1]->id;
            }

            $childRole = $this->makeRole();

            // Create base role
            $baseRoles[] =  $this->makeRole([
                'parent_id' => $parentId,
                'display_name' => $childRole->display_name,
                'site_id' => null
            ]);

            if($i < 3){
                $childRoles[] = $childRole;
            }
        }

        $children = $childRoles[0]->getChildren();

        $this->assertEquals($childRoles,$children);
    }
}

MakeRoleTrait

namespace Tests\Traits;


use Faker\Factory as Faker;
use App\Models\Role;
use App\Repositories\RoleRepository;

trait MakeRoleTrait
{
    /**
     * Create fake instance of Role and save it in database
     *
     * @param array $roleFields
     * @return Role
     */
    public function makeRole($roleFields = [])
    {
        /** @var RoleRepository $roleRepo */
        $roleRepo = \App::make(RoleRepository::class);
        $theme = $this->fakeRoleData($roleFields);
        return $roleRepo->skipPresenter()->create($theme);
    }

    /**
     * Get fake instance of Role
     *
     * @param array $roleFields
     * @return Role
     */
    public function fakeRole($roleFields = [])
    {
        return new Role($this->fakeRoleData($roleFields));
    }

    /**
     * Get fake data of Role
     *
     * @param array $roleFields
     * @return array
     */
    public function fakeRoleData($roleFields = [])
    {
        $role = factory(\App\Models\Role::class,1)->make();
        $array = $role->first()->toArray();

        $array = array_merge(
            $array,
            $roleFields
        );

        return $array;
    }
}
4
  • 1
    The line <env name="DB_CONNECTION" value="..."/> in phpunit.xml should tell Laravel which connection to use while testing. It should be a separate connection to the main app, so it runs its queries there instead. Make sure env('DB_CONNECTION') has an effect on your config/database.php , too Commented Mar 2, 2018 at 19:43
  • Thanks for the reply, but I dont think this is what Im looking for. The DB_CONNECTION in all of my other tests are set to mysql just like it is in this one, but the other tests dont save to the database. There is no line in my phpunit.xml for DB_CONNECTION, hence its defaulting to mysql. Commented Mar 2, 2018 at 19:51
  • 1
    You really should have the tests run on a separate database. That said, maybe the other tests are using the refresh database traits? Or if it's an older version of Laravel, one of the style DatabaseTransactions traits that perform a rollback every time? Commented Mar 2, 2018 at 19:53
  • Thats the one! Set this as your answer, Ill explain and accept. Commented Mar 2, 2018 at 19:58

1 Answer 1

5

Laravel has traits to roll-back changes made to the database. In 5.6, it's the RefreshDatabase trait - in some earlier versions it was DatabaseTransactions instead.

These traits should be added to all tests that make database updates/inserts.

(For additional ease (and safety), tests should run on a separate database connection with a separate copy of the database, too.)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.