Jonjie's avatar
Level 12

Generating new test with --unit flag is not importing the correct TestCase Class

Why laravel is using the use PHPUnit\Framework\TestCase; when generating unit test instead of using the use Tests\TestCase; when running php artisan make:test ExampleTest --unit command?

I just got an error with undefined method withoutExceptionHandling() and found out that it is not importing the correct class. It was working before, but not in laravel v9. Any reason why?

0 likes
20 replies
tykus's avatar

Because a Unit test should not require the framework to be bootstrapped (as a Feature test would).

martinbean's avatar
Level 80

@jonjie It is importing the correct class. Unit tests extend the PHPUnit test case because you should be able to run a unit test without the framework, a database, or any other external service. If you need to interact with any of these, then it’s not a unit test.

Jonjie's avatar
Level 12

@martinbean But how can I use the withoutExceptionHandling method if I use the default import?

Sinnbeck's avatar

@Jonjie There shouldnt be any exception handling as you arent using laravel. But you can catch them with phpunit if you want.

$this->expectException(MyException::class);

Maybe show the test and the problem

martinbean's avatar

@Jonjie You can’t, because you shouldn’t be using that method. Again, unit tests should be able to be ran without the framework.

Jonjie's avatar
Level 12

@Sinnbeck Please see my code below:

/** @test */
public function it_has_a_path()
{
    $this->withoutExceptionHandling();
    $product = Product::factory()->create();
    
    $this->assertEquals($product->path(), $product->path());
}

But when I put the class from PHPUnit back, I always get an error.

  1. Tests\Unit\HomeProductTest::it_has_a_path InvalidArgumentException: Unknown format "words"
Sinnbeck's avatar

@Jonjie you are trying to create a product which means using the database, which means it isn't a unit test. Martin already mentioned this

Sinnbeck's avatar

Also why are you comparing it to it self? Is that a mistake?

Jonjie's avatar
Level 12

@Sinnbeck Yeah, but why Jeffrey Way is using Tests\TestCase instead of PHPUnit\Framework\TestCase for his unit tests?

Sinnbeck's avatar

@Jonjie You would need to ask him. I personally think that is bad practice as the unit test is then no longer a test of a single unit :)

1 like
tykus's avatar

@jonjie what are you testing that requires your need to disable exception handling? Perhaps, you are not writing a Unit Test at all?

Jonjie's avatar
Level 12

@tykus Please see my code below:

/** @test */
public function it_has_a_path()
{
    $this->withoutExceptionHandling();
    $product = Product::factory()->create();
    
    $this->assertEquals('/api/products/' . $product->id, $product->path());
}

But when I put the class from PHPUnit back, I always get an error.

  1. Tests\Unit\HomeProductTest::it_has_a_path InvalidArgumentException: Unknown format "words"
tykus's avatar

@Jonjie you should not use the Factory (and database) to perform a Unit Test. Also, your assertion is nonsense.

/** @test */
public function it_has_a_path()
{
    $product = new Product;

    $this->assertEquals('some/path', $product->path());
}
tykus's avatar

@Jonjie did he actually assert that $product->path() equals $product->path()?

And also, does his Unit test class extend the PHPUnit\Framework\TestCase or the Tests\TestCase?

Jonjie's avatar
Level 12

@tykus Sorry for the old code, but he's using factory here

tykus's avatar

@Jonjie so the Unit test must be using the Tests\TestCase base class? Otherwise, he could not be using framework features.

Jonjie's avatar
Level 12

@tykus Yes, he's using Tests\TestCase. Is it okay to use factory (and database) when doing unit tests?

tykus's avatar

@Jonjie ok, well there you go then... there will be dissenting opinions on whether this is a true Unit test; I would argue it is not because you are not isolating the "unit". But I also understand that this type of test would be better than no test at all, so go for it if it works for you.

If you want the framework conveniences, the you must CreateApplication (which the Tests\TestCase class does, but PHPUnit\Framework\TestCase doe not.

Aside, the assertion still is nonsense... IMHO!

Please or to participate in this conversation.