unit-testing - Magento 2 : Proxy and Factory generation in unit tests scope

标签 unit-testing proxy factory magento2

我正在尝试为具有 Proxy 的 Magento 2(版本 2.2.0)类创建单元测试在构造函数中注入(inject)的类。 根据 Magento 文档,代理是生成的代码,就像工厂一样。

但是,在单元测试范围内(代码生成在 dev/tests/unit/tmp/generated 目录中),不会生成 Proxies 类。仅生成工厂。

在单元测试范围内没有生成代理类有什么原因吗?

假设:根据文档,代理注入(inject)应该在 di.xml 配置文件中

<type name="FastLoading">
    <arguments>
        <argument name="slowLoading" xsi:type="object">SlowLoading\Proxy</argument>
    </arguments>
</type>

而不是直接在构造函数中注入(inject):

class FastLoading
{
    protected $slowLoading;

    public function __construct(
        SlowLoading\Proxy $slowLoading
    ){
        $this->slowLoading = slowLoading;
    }
}

那么,直接在构造函数中注入(inject)代理类是一种不好的做法吗?

单元测试范围内工厂生成的另一个问题,假设以下工厂生成:

// dev/tests/unit/tmp/generated/code/Magento/Framework/Api/SearchCriteriaBuilderFactory.php
namespace Magento\Framework\Api;

class SearchCriteriaBuilderFactory
{

    public function create(array $data = [])
    {
    }  
}

生成的 create() 方法为空并在单元测试范围内返回 null 的原因是什么?

谢谢。

最佳答案

  1. 首先,假设代理类应该在 xml 中配置而不是在构造函数中注入(inject)它是错误的,因为您无法配置构造函数不需要的参数。因此两者是互补的。

You can configure the class constructor arguments in your di.xml in the argument node. The object manager injects these arguments into the class during creation. The name of the argument configured in the XML file must correspond to the name of the parameter in the constructor in the configured class.

  1. 其次,在生产中,您使用具有不同依赖项配置的不同对象管理器。当您在某个阶段使用开发人员/生产对象管理器创建工厂时,会注入(inject)负责生成工厂的动态工厂对象(见下图) factory creation stack

    分别对于开发者模式动态类是 供应商/magento/framework/ObjectManager/Factory/Dynamic/Developer.php 和 生产方式 供应商/magento/framework/ObjectManager/Factory/Dynamic/Production.php 对于 UT 的 ObjectManager,它或多或少是一个带有一些附加实用程序的模拟包装器,因此它不会生成任何真实的类。实际上,::getObject() 将在第 161 行代码上抛出异常。如您所见,那是因为除了一些反射魔法之外别无其他。

  2. 关于代理问题,根据 ad.1,您的解决方案甚至不可能,而且由于与工厂相同的原因,未生成代理类。

从 UT 的角度来看,我无法想象您需要任何自动生成的类的情况。所有依赖项都应该被模拟,生成的类永远不会被直接测试。对于工厂或代理,创建模拟如下:

$mockSearachCriteriaBuilder = $this->getMockBuilder(Magento\Framework\Api\SearchCriteriaBuilderFactory::class)->disableOriginalConstructor()->setMethods([set_your_methods_stubs]->getMock()

然后将其作为依赖项注入(inject)到被测类的构造函数中,例如。

$this->om = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->om->getObject('your\class\name', ['searchCriteriaBuilder' => $this->mockSearchCriteriaBuilder];

这只是一个示例,但它表明即使您的问题很有趣,问题也不存在,因为真正的解决方案在于完全不同的方法。

更新: 不,模拟不需要类的存在,类型就是全部,所以如果模拟可以像给定类型一样工作,那么源类就不必存在。

class FactoryTest extends \PHPUnit_Framework_TestCase
{
    public function testSomething()
    {
        $mock = $this->getMock(UnknownClass::class, ['test']);
        $mock->expects($this->once())->method('test')->willReturn(true);
        $this->assertTrue($mock->test());
    }
}

上面的测试将通过,但没有像 UnknownClass 这样的东西。此外,没有 createMock 方法。单元测试就是隔离。如果测试需要的不仅仅是被测类,那么它就违反了这个原则。这就是 mock 派上用场的地方。

关于unit-testing - Magento 2 : Proxy and Factory generation in unit tests scope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47080851/

相关文章:

ssl - 使用 https 时基于主机的 nginx 代理

c# - 当您的方法设计用于执行许多任务时如何使用 TDD

angularjs - ngMock 将 $scope local 注入(inject) Controller

visual-studio - 如何开始单元测试?

tomcat - 在代理后面的 tomcat 上运行的 servlet 如何知道浏览器向其发送请求的服务器名称

javascript - AngularJs 中的简单工厂调用给出错误

unit-testing - 如何在 Visual Studio 2012 Professional 中连续运行单元测试?

http - 如何像在 curl 中那样在 clojure http 请求中设置 'no proxy'?

c++ - 如何在模板类函数中分配结构值?

java - Java 的最佳设计解析具有不同 header 和模型对象的多个 CSV 文件