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

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.

Firstly, assumption that proxy class should be configured in xml instead of injecting it in constructor is wrong because you are not able to configure arguments that are not already expected by constructor. Therefore both are complementary.
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.

Related

Gmock const method not called instead calling the original method

I have interface which is defined as
in .h file
namespace diagnostic{
class class1interface{
virtual int readpowerstate()const =0;
virtual int readparameters() = 0;
}
class class1 : public class1interface{
int readpowerstate()const;
int readparameters();}};
in .cc file i have the function
int diagnostic::readparameters(){
if(diagnostic::readpowerstate ==1)
{ //Dothis}
else
{return 0}}
i have to execute the else part since by default the if will get called when i run the program. So i tried to use gmock as follows.
class Mock_class : public diagnostic::class1interface{
public:
Mock_class(){}
MOCK_METHOD0(readparameters,int());
MOCK_CONST_METHOD0(readpowerstate,int());};
and the gmock test i wrote as follows
// Test the failure of Read Parameters
TEST_F(TestBase, readParam_failure){
Mock_class mock_class;
class1 *class_dummmy = new class1();
EXPECT_CALL(mock_class, readpowerstate()).WillOnce(Return(0));
class_dummy->readparameters;
EXPECT_EQ(0, class_dummy->readparameters());}
when i'm executing this program i'm getting the error that
error: Actual function call count doesn't match
EXPECT_CALL(mock_class, readpowerstate())...
Expected: to be called at least once
Actual: never called - unsatisfied and active
what is the solution for this since i'm new to gmock.
Module tests are all about testing an isolated module (like an instance of a selected class) in a mocked environment, specifically, how that module communicates with other objects, and how it responds to various results of these calls. To make this possible, one uses mocks in place of that other real objects. Mock classes allow to both:
configure expectations regarding, e.g., the amount/sequence of calls and/or the values of arguments of these calls to specific functions, and verify those by registering all interactions;
program the results of these expected calls that are returned as if a real object performed some action and responded to the object under test.
This makes it possible to test an object as if it were surrounded by real components, without actually having those. E.g., a device manager can be tested on how it responds to device failures, by mocking a class representing a device and programming that mock to return an error code when some status function is invoked by the manager. That is, no real device class is used, and also, no real (faulty!) device itself is needed to be connected and configured. The mock will pretend to be that device, and what's important, this will all be on a software level.
This, however, is possible only if the class itself is designed in a way that allows us to somehow inject mocked objects in place of their real counterparts. Most importantly, the objects in the system need to communicate via interfaces and virtual calls. That is, the aforementioned device manager should not be communicating with, e.g., DeviceA (a concrete class name), but instead, some DeviceInterface, and so both DeviceA and a newly created mock DeviceMock could implement that interface and be used in that manager. This way the manager will not even know that it is beeing tested and communicates with a mocked object, and not the real device wrapper.
That is, currently, although you create a mock for class1interface you don't actually use that mock. Instead, you try to test class1. Creating a mock for class1interface is useful only if you aim to test some other component (like a class) that communicates with class1 through class1interface, not class1 itself.
So, having a mock for class1, you can e.g. test class2. But this requires this class design to meet the conditions I mentioned previously: communicating via interfaces and ability to inject a mock class.
So to meet the conditions, you'd have to rewrite the code:
int class2::readdata()
{
std::unique_ptr<diagnostic::class1interface> classint
= std::make_unique<diagnostic::class1>();
int value = classint->readparameters();
return value;
}
to (it's just an example of questionable usefulness, you'd have to adjust it to your needs):
int class2::readdata(diagnostic::classinterface* classint)
{
int value = classint->readparameters();
return value;
}
And so you could write a test for class2, injecting a mock of class1:
TEST_F( TestClass2, readParam_failure )
{
// Mocks configuration
Mock_class mock_class;
EXPECT_CALL( mock_class, readparameters() ).WillOnce(Return(0));
// System under test configuration
diagnostic::class2 sut;
// Test itself
EXPECT_EQ( 0, sut.readdata(&mock_class) );
}
This way you check that the call to class2::readdata is properly fowarded to class1interface::readparameters, and its result is returned.

How can I open class only to test class?

I'm mainly a Java developer and wonder about structure when writing unit test in kotlin,
Assuming there's no package-private in kotlin
private to restrict visibility to the file
internal to restrict visibility to the module
How can I open class only to test class ?
Must I write test inside kotlin class or open class to all module (internal)?
What's the kotlin way to open method for unit test only?
EDIT
Found similar question/request in kotlin discuss by #bentolor:
How am I supposed to do unit / whitebox testing properly? I want to write test code which tests class-internal functionality which I do not want to expose to other classes except my test class at all.
The package protected visibility is an excellent way to achieve this. Whereas Kotlin now requires me to make these methods effectively public and litter the visible API of my component all-over the project be able to test them.
In my view internal is more or less public as it has a much larger scope. Most projects have sth. around 1 - 5 “modules” in the Kotlin sense.
Really strongly asking/advocating for package-local visibility here.
Formally it is not possible to do this honestly on JVM, because class couldn't be open for subset of possible interiters.
However it can be partially done by the following trick:
open class SomeClass internal constructor(val configurableParameter: Int) {
companion object {
private const val defaultInput = 123
fun create() = SomeClass(defaultInput)
}
}
The constructor of this class can be called only from the same module (or from tests). And class is public, so anyone can use it. However from external modules you have only two ways of the class construction: companion object or reflection.
And finally you couldn't inherit from this class at any other modules, because constructor is internal.
For Android developers only, there's AndroidX VisibleForTesting annotation
Denotes that the class, method or field has its visibility relaxed, so that it is more widely visible than otherwise necessary to make code testable

Mocking a file write process in googlemock

I am just starting with mocking using googlemock for a C++ project. In my case, my class to be tested observes a file that is written to, and whenever a minimal amount of new data has been written, it starts doing some work.
What I need is a mock class for the process writing to the file. As far as I understand things, I need to completely implement this "writing to file" functionality in form of (for googlemock) a virtual class from which a mock class is derived? The mock wrapper is finally used for testing and evaluation purposes, right?
Thanks for help!
Mocks, in google mock terms, are objects used to validate that your code under test performs certain operations on them.
What you describe is not a mock, but a utility class that triggers your code under test operations.
What does your class do when it detects that the file it observes is written to? If, for instance, it performs a call to another object, then you could use a mock object to check that it gets called with the right parameters, e.g. the new bulk of data written to the file.
I am assuming that an object of your "observer" class is notified
that minimal amount of data has been written by an object of
the "writter" class. In that case, you need to implement an abstract
class that represents an interface for your "writter" class, and have
your real "writter" class inherit from it and override its virtual functions.
Also, have your mock "writter" class implementation inherit from this interface and
and create mock implementations using MOCK_METHODn.
Then, have your "observer" class receive notifications from "writter" object
using a pointer to the abstract class. This way, you can use dependency
injection to switch implementation during testing phase by creating a mock
"writter" object and passing its address to "observer" object (instead of an address to a real "writter"
object) and setup test cases using EXPECT_CALL on the mock object.
This is the best advice I can give since you did not provide us with a detailed description of your classes.
EDIT:
Concerning the implementation of your real "writter" class: You do not have to create it immediately, you can use the mock class for now to test the behavior of the "observer" class and leave the implementation for later. You will, of course, have to implement it eventually since it has to be used in production code.

Using gmock without dependency injection

I'm just learning to use Google Mock. It works fine when I test a class to which I can pass the mocked object as a pointer or reference (dependency injection). When I have a class which doesn't use DI, I haven't found a solution.
We currently have a lot of code which doesn't use DI and interfaces, for example:
#include "ReadDbObjects.h"
class ObjectManager
{
public:
ObjectManager()
{
ReadDbObjects db_reader;
mObjects = db_reader.ReadAll();
}
private:
vector<MyObject> mObjects;
}
(this is extremly simplified, but should explain the problem)
We currently test something like this by creating just for the unit test a file called ReadDbObjects.cpp (which includes the original ReadObjects.h with the class declaration), which is statically linked to the unit test. In this file, we mock the ReadAll-Method, so it returns the objects we need for the test. This file is hard to maintain and it needs another file which is known both in the ReadObjects.cpp and the unit test, so values between the test and the mocked ReadObjects-class can be passed in both directions.
Is there a way to mock ReadObjects using gmock in this example?
Can gmock be used, when I need to mock a base class? Here we use the same mechanism by linking a mocked cpp base class file into the unit test.

Unit testing with ServiceLocator

I am doing a unit test on a class that uses the unity dependency injection framework.
This returns null:
ServiceLocator.Current.GetInstance();
How can I get it to return a mock object or just the object itself?
You could make use of Poor Man's injection. Create a default constructor which retrieves the dependencies from the service locator, and forward those dependencies to a "real" constructor which takes them as parameters. That takes care of production situations.
Then when testing the class in question, pass in a fake/mock version of the dependencies to the "real" constructor, bypassing the default one altogether.
MSDN has this example that shows how to implement the service locator pattern with Unity. Essentially, you should pass the service locator object as a constructor argument of your class. This enables you to pass a MockUnityResolver, allowing you to take full control in a unit test.
[TestMethod]
public void InitCallsRunOnNewsController()
{
MockUnityResolver container = new MockUnityResolver();
var controller = new MockNewsController();
container.Bag.Add(typeof(INewsController), controller);
var newsModule = new NewsModule(container);
newsModule.Initialize();
Assert.IsTrue(controller.RunCalled);
}
Are you testing your core "DI integration" code? If not, your normal code should never (well, rarely) be interacting with your DI framework.
Normally your dependencies will be injected via constructor injection, and when testing, you can instead supply mock objects as those constructor dependencies. For example:
public class Foo {
public Foo (IBar bar) {
bar.Lift ();
}
}
With the above code, you can simply mock IBar, and pass it to the Foo constructor.
You can always setup a Container+ServiceLocator and actually fulfill the required dependencies, for example, by registering mocks. See code examples #4 for how to setup a container/locator:
http://blogs.msdn.com/b/miah/archive/2009/05/12/servicelocator-and-unity-be-careful.aspx