So I recently stumbled upon a problem while writing a unit test in Magento 2. You can read more about the problem in question here.
Vinai told me it is generally bad practice to use the object manager in unit tests:
In Unit tests, don't use the ObjectManager at all. Just instantiate your class with new, since all dependencies are test doubles anyway. Less magic makes for easier debugging. Especially like in your case where there is only a single dependency.
Now... I did what he suggested, and I changed my Object-Manager based constructing of the class to a vanilla new
-statement and it worked:
So instead of this:
$this->sourceModel = (new ObjectManager($this))
->getObject(
\Custom\Shipping\Model\Config\Source\ProductTypes::class,
[
'Config' => $this->configHelperMock
]
);
I did this:
$this->sourceModel = new \Custom\Shipping\Model\Config\Source\ProductTypes($this->configHelperMock);
But I also have another test that needed to stub a helper. This I did like this:
$this->configHelper = (new ObjectManager($this))
->getObject(
\Custom\Shipping\Helper\Config::class,
[
'scopeConfig' => $this->scopeConfigMock
]
);
Now if you look at Magentos' AbstractHelper
-class, you'll note that it has one constructor argument: Magento\Framework\App\Helper\Context
. So I figured what the Object Manager does with above constructor call, is it sets the scopeConfig
-parameter of my Context
-object to my mocked object. I hope this assumption is correct.
But... to get back to Vinais' statement to not use the Object Manager, how would you do this without the Object Manager? Mock the entire Context object? Or is the Object Manager the correct strategy to use in this particular scenario?
I'm really trying to understand what's the correct way to write unit tests for Magento, because for now it seems to me that:
- You need to use the Object Manager when you want to mock the content of the context-object
- You don't need to use the Object Manager in all other scenarios.
Can anyone shine a light on this? The Magento 2 documentation is lacking of a more in-depth explanation on how to write proper unit tests.