英文:
When to use TestCase over KernelTestCase in Symfony testing
问题
我刚刚开始在Symfony框架的上下文中编写测试,我想知道什么时候只使用TestCase类而不是KernelTestCase。
一些背景信息:我需要测试我的自定义服务,这些服务由我的控制器调用。所有业务逻辑都存在于我的服务中。
我有一些用于CRUD操作的方法,其他用于发送电子邮件等等...
我需要知道何时使用TestCase而不是KernelTestCase,因为我看到的主要区别是,使用KernelTestCase可以调用容器而不是实例化您的服务,那么何时使用TestCase比KernelTestCase更合适,反之亦然?
官方文档说:
集成测试将测试应用程序的较大部分,与单元测试相比(例如,服务的组合)。集成测试可能希望使用Symfony Kernel从依赖注入容器中获取服务。
这是否意味着如果我有一个使用许多其他服务的服务,我需要使用KernelTestCase?如果是这样,使用KernelTestCase而不是TestCase的界限在哪里?
希望我表达清楚。
英文:
I just started writing tests in the context of Symfony framework, and I'm wondering when to just use TestCase class over KernelTestCase.
A bit of context : I need to test my custom services which are called by my controllers. All the business logic lives inside my services.
I have methods that are used for crud actions, others for email sendings etc...
I need to know when to use TestCase over KernelTestCase because the main difference I see is that with KernelTestCase you can call the container instead of instantiating your services, so when is TestCase more appropriate than KernelTestCase and the other way around ?
The official documentation says :
> An integration test will test a larger part of your application
> compared to a unit test (e.g. a combination of services). Integration
> tests might want to use the Symfony Kernel to fetch a service from the
> dependency injection container.
So does this mean that If I have a service that uses many other services I need to use KernelTestCase ? If so, what's to borderline to go with KernelTestCase over TestCase ?
Hope I'm clear.
答案1
得分: 3
不一定!
通过使用PHPUnit的TestCase
,您可以轻松地模拟依赖项(通过扩展它们来实例化虚拟对象),甚至对它们的方法调用进行期望:
$dependency = self::createMock(MyDependencyService::class);
$dependency->expects(self::once())->method('someMethodName');
$service = new Service($dependency);
$service->testedMethod();
在这里,我们期望$dependency
模拟对象的someMethodName()
方法被调用一次。如果没有,测试将失败。您可以对参数进行更复杂的断言,并定义返回的值。
使用Symfony的KernelTestCase
,您可以访问服务容器中的服务。当您真正需要一个服务而不是一个不执行任何操作的模拟对象时,这非常有用。
例如,您可以请求序列化器将一些JSON输入转换为DTO:
$serializer = self::getContainer()->get(SerializerInterface::class);
$service = new Service($serializer);
在某些情况下,甚至可以从服务容器中获取完全配置的服务,或在这样做之前替换容器中的服务。
请注意,使用KernelTestCase
并不意味着在每个测试中都要使用测试服务容器,您可能只需要在一个测试中使用它。
这真的取决于您要测试的行为和您服务的依赖关系。如果您需要获取真实服务来测试无法自己实例化的自定义服务,请使用KernelTestCase
,但如果可以避免(使用Kernel和服务容器可能会减慢测试套件的速度),请使用TestCase
并使用模拟对象。
英文:
>So does this mean that If I have a service that uses many other services I need to use KernelTestCase ?
Not necessarily !
By using a TestCase
(from PHPUnit) you can easily mock dependencies (instanciate fake objects by extending them) and even make expectations on their method calls:
$dependency = self::createMock(MyDependencyService::class);
$dependency->expects(self::once())->method('someMethodName');
$service = new Service($dependency);
$service->testedMethod();
Here we expect the $dependency
mock object to have its someMethodName()
method be called once. If not, the test will fail. You can make more complex assertions about arguments and define the returned value.
Using KernelTestCase
(from Symfony), you have access to services from the service container. This is very useful when you really need a service and not a mock object that does not really do anything.<br>
For example, you could request the serializer to transform some JSON input into DTOs:
$serializer = self::getContainer()->get(SerializerInterface::class);
$service = new Service($serializer);
In some cases, you can even get your fully configured service from the service container, or replace a service in the container before doing so.<br>
Note that using KernelTestCase
does not imply the use of the testing service container in every test, you may only need it in a single test.
It really depends on the behaviours you want to test and the dependencies of your service. If you need to get real services to test your custom one that you cannot really instanciate yourself, go with KernelTestCase
, but if you can avoid it (using the Kernel and service container can slow your tests suite), go with TestCase
and use mock objects.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论