如何使用依赖关系对工厂进行单元测试

时间:2017-04-08 11:12:12

标签: zend-framework doctrine-orm phpunit tdd

如何使用实体管理器测试我的工厂?我有一个错误,因为我需要让我的容器返回一个从doctrine创建的类的实例(我甚至不知道返回了什么)。

如何创建一个可以通过的测试?

// factory i want to test
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
    $googleAppOption = $container->get(GoogleAppOptions::class);
    $em = $container->get('doctrine.entity_manager.orm_default');
    return new GoogleTokenHandler($googleAppOption, new GoogleTokenClient(), $em);
}

//test function
 public function testReturnsTokenHandlerInstance()
{
    $googleOptionsFactory = new GoogleOptionsFactory();
    $googleOptions = $googleOptionsFactory($this->container->reveal(), null);
    $this->container->get(GoogleAppOptions::class)->willReturn($googleOptions);
    $googleTokenHandlerFactory = new GoogleTokenHandlerFactory($this->container);
    $tokenHandler = $googleTokenHandlerFactory($this->container->reveal(), null);
    $this->assertInstanceof(GoogleTokenHandler::class, $tokenHandler);

}

1 个答案:

答案 0 :(得分:1)

事实上,这很难测试,这是一个很好的迹象,表明这有点臭。在你的情况下,很明显,容器被注入然后用于定位服务。我建议重写这个类,以在构造函数中注入OptionsFactory(或者更好的只是选项)和EntityManager以及动态创建的GoogleClient。你会得到的是一个看起来像这样的调用:

'post_type' => 'drama',
'showposts' => 10,
'meta_key' => $valuez,
'orderby' => 'meta_value_datetime' 

您可以看到,既没有使用return new GoogleTokenHandler( $this->optionsFactory, $this->tokenClient, $this->entityManager ); ,也没有使用$requestedName传递给$options。这有点奇怪,但这不会打扰我们的测试。现在,您可以简单地模拟测试中的服务,并检查invoke是否返回正确的实例:

__invoke

您可以对您的类执行相同的操作,但基本上您必须添加一个Container,然后为从其中获取的所有服务存根get-method。例如,您在代码段中缺少实体管理器。如果在您的方法中创建的GoogleTokenClient需要一些参数/选项,则无法模拟该行为,事实上,如果不更改代码,您将无法将其切换出来。然而,通过在构造函数中注入它,您可以重新配置容器以传入不同的对象。

对于子孙后代,你的整个工厂可能看起来像这样:

public function testFactoryInvokeReturnsInstance()
{
    $optionsFactory = $this->prophesize(OptionsFactory::class);
    $tokenClient = $this->prophesize(GoogleTokenClient::class);
    $entityManager = $this->prophesize(EntityManager::class);

    $factory = new MyFactory(
        $optionsFactory->reveal(),
        $tokenClient->reveal(),
        $entityManager->reveal()
    );

    $this->assertInstanceOf(GoogleTokenHandler::class, $factory->__invoke());
    // Alternatively you can use the __invoke-magic directly:
    $this->assertInstanceOf(GoogleTokenHandler::class, $factory());
}