如何提供模拟实体管理器来测试服务类?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何提供模拟实体管理器来测试服务类?相关的知识,希望对你有一定的参考价值。

我的Symfony(3.4)应用程序中有一个服务类(OutletScraper)。该类使用实体管理器和Bazinga Geocoder捆绑包提供的地理编码服务。我已经成功配置了两个,以便我可以在我的服务类中调用它们。每当我需要服务时,我都会从容器中调用它,因此实体管理器和地理编码器包已经注入其中。

测试时,我知道我可以模拟实体管理器,然后将其提供给我的测试类。当我从容器访问服务类时,如何覆盖传递给构造函数的内容?即,以便我可以提供模拟实体管理器,而不是注入真实的实体管理器。我试图手动实例化服务类的对象:

$outletScraper = new OutletScraper(new Provider(), $this->createMock(EntityManagerInterface::class));

但是,这样做时会出现以下错误:

Error: Cannot instantiate interface GeocoderProviderProvider

如何正确实例化此类?我是否需要从服务容器(它设置为私有)调用它?感谢任何帮助。

答案

您对实体管理器的模拟工作正常,问题是地理编码器提供商。就像EntityManagerInterface一样,GeocoderProviderProvider也是一个界面。图书馆维护者只是选择省略后缀。

这意味着您不能只创建它,而是必须传递实现接口的具体类,如GeocoderProviderGoogleMapsGoogleMaps,如果您确实想要进行地理编码调用或模拟提供程序。

如果要检查配置的地理编码提供程序是否有效,可以使用Symfony的WebTestCase编写功能测试,大致如下所示:

<?php

namespace AppBundleTestsScraper;

use SymfonyBundleFrameworkBundleTestWebTestCase;

class OutletScraperTest extends WebTestCase
{
    public function testFindsLocation()
    {
        // This will instantiate your Symfony application in the test environment
        $client = static::createClient();

        $container = $client->getContainer();
        // Replace the class name with the service id, if you use artificial service ids like "app.outlet_scraper"
        $scraper = $container->get(OutletScraper::class);

        // Call whatever method you want to test on your outlet scraper
        $result = $scraper->someMethod();

        // Assert result matches expectations
        $this->assertEquals(..., $result);
    }
}

但要小心,这将使用您为应用程序配置的OutletScraper,并具有两个实际的依赖关系。因此,您的地理编码提供程序将对您使用的任何提供程序进行实际调用,这可能会占用请求,这可能是有限的。您还将使用真正的Doctrine EntityManager,这意味着您写入数据库的任何内容都将被实际写入。特别是对于数据库,您应该创建一个单独的测试数据库并在app/config/config_test.yaml中进行配置。

另一答案

我的建议是,如果你试图单独测试这项服务,你也应该嘲笑GeocoderProviderProvider。否则,您的测试断言可能会产生不同的结果,具体取决于您运行它们的时间。

如果你要使用这个模拟器,你甚至可以创建自己的测试类来实现该接口,这样你就可以在测试环境中自己准备不同的输出。

以上是关于如何提供模拟实体管理器来测试服务类?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用实体框架测试视图?

.NET 中的单元测试:如何模拟实体数据提供者

如何模拟EntityManager?

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

如何在C#中模拟基类属性或方法

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段