I'm trying to create an Unit Test for a Magento 2 (version 2.2.0) Class that have a Proxy Class injected in constructor. According to the Magento documentation, Proxies are generated code, like Factories.
However, in Unit Test scope (code generation is in dev/tests/unit/tmp/generated directory), Proxies class are not generated. Only Factories is generated.
Is there any reason why Proxy Class is not generated in Unit Test scope ?
Hypothesis : according to the documentation, the Proxy injection should be in di.xml configuration file
<type name="FastLoading">
<arguments>
<argument name="slowLoading" xsi:type="object">SlowLoading\Proxy</argument>
</arguments>
</type>
instead of injecting directly in constructor :
class FastLoading
{
protected $slowLoading;
public function __construct(
SlowLoading\Proxy $slowLoading
){
$this->slowLoading = slowLoading;
}
}
So, inject a Proxy Class directly in constructor is a bad practice ?
Another question for Factory generation in unit test scope, assuming the following Factory generated :
// dev/tests/unit/tmp/generated/code/Magento/Framework/Api/SearchCriteriaBuilderFactory.php
namespace Magento\Framework\Api;
class SearchCriteriaBuilderFactory
{
public function create(array $data = [])
{
}
}
What is the reason that the create() method generated is empty and so return null in unit test scope ?
Thanks.
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.
Secondly, in production you are using different Object Manager with different configuration of dependencies. When you are creating factory with developer/production object manager at some stage there is injected dynamic factory object responsible for generation of factory (see pic below)

Respectively, for developer mode dynamic class is vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php and for production mode vendor/magento/framework/ObjectManager/Factory/Dynamic/Production.php In case of ObjectManager for UT it is a more or less a wrapper for mockery with some additional utilities and therefore it will not generate any real class. Actually, ::getObject() will throw an exception on 161 line of code. As you can see there it is because there is nothing more but some reflection magic.
Regarding the proxy question, in light of ad.1, you solution is not even possible plus, the proxy class is not generated for the same reasons as with factory.
A little bit more from UT perspective, I can't imagine situation when you would need any of the autogenerated class. All dependencies should be mocked and generated class will never be tested directly. Either, for factory or proxy, create mock like:
$mockSearachCriteriaBuilder = $this->getMockBuilder(Magento\Framework\Api\SearchCriteriaBuilderFactory::class)->disableOriginalConstructor()->setMethods([set_your_methods_stubs]->getMock()
And then inject it as a dependency in constructor of class under test eg.
$this->om = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->om->getObject('your\class\name', ['searchCriteriaBuilder' => $this->mockSearchCriteriaBuilder];
This is just an example but it shows that even if your question was interesting, the problem does not exist because the real solution lies in a totally different approach.
Update: No, presence of class is not required for a mock, the type is what is all about so if mock can act like a given type then source class do not have to exist.
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());
}
}
The test above will pass but there is nothing like UnknownClass. Also, there is no createMock method. Unit Test is all about isolation. If test requires anything more than class under test then it violate this principle. And here is where mockery comes in handy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With