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
Related
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.
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.
In mocking frameworks, you can mock an object or spy on it. What's the difference between the two and when would/should I use one over the other?
Looking at Mockito, for example, I see similar things being done using spies and mocks, but I am unsure as to the distinction between the two.
Mock object replace mocked class entirely, returning recorded or default values. You can create mock out of "thin air". This is what is mostly used during unit testing.
When spying, you take an existing object and "replace" only some methods. This is useful when you have a huge class and only want to mock certain methods (partial mocking). Let me quote Mockito documentation:
You can create spies of real objects. When you use the spy then the real methods are called (unless a method was stubbed).
Real spies should be used carefully and occasionally, for example when dealing with legacy code.
When in doubt, use mocks.
I'll try to explain using an example here:
// Difference between mocking, stubbing and spying
#Test
public void differenceBetweenMockingSpyingAndStubbing() {
List list = new ArrayList();
list.add("abc");
assertEquals(1, list.size());
List mockedList = spy(list);
when(mockedList.size()).thenReturn(10);
assertEquals(10, mockedList.size());
}
Here, we had initial real object list, in which we added one element and expected size to be one.
We spy real object meaning that we can instruct which method to be stubbed. So we declared that we stubbed method - size() on spy object which will return 10, no matter what is actual size.
In a nutshell, you will spy real object and stub some of the methods.
Mockito warns that partial mocking isn't a good practice and you should revise your Object Oriented architecture. Spy (or partial mocking) is recommended to test legacy code.
Based on Mocks Aren't Stubs by Martin Fowler:
Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
In Mockito if you assign any object to instance variable of Mock Object then does not affect on Mock Object.
But in case of Spy, if you assign any object to instance variable of Spy Object then does affect on Spy Object because of Spy act like real-time object modification.
For a reference example are
#RunWith(MockitoJUnitRunner.class)
public class MockSpyExampleTest {
#Mock
private List<String> mockList;
#Spy
private List<String> spyList = new ArrayList();
#Test
public void testMockList() {
//by default, calling the methods of mock object will do nothing
mockList.add("test");
assertNull(mockList.get(0));
}
#Test
public void testSpyList() {
//spy object will call the real method when not stub
spyList.add("test");
assertEquals("test", spyList.get(0));
}
}
Reference: http://javapointers.com/tutorial/difference-between-spy-and-mock-in-mockito/
When using mock objects, the default behavior of the method when not stub is do nothing. Simple means, if its a void method, then it will do nothing when you call the method or if its a method with a return then it may return null, empty or the default value.
While in spy objects, of course, since it is a real method, when you are not stubbing the method, then it will call the real method behavior. If you want to change and mock the method, then you need to stub it.
Spies have two definitions. One, is where the real method is called, another where, no functionality is called and only null or null equivalent values are returned, but methods were called, and they're state was recorded, commonly like, method x was called y times.
If we want to avoid calling external services and just want to test the logic inside the method then use mock.
If we want to call the external services and use the real dependency i.e to run the program as it is and just stub specific methods then use spy
So I'm wondering about how unit testing works in regards to dealing external dependencies. Here and elsewhere I've become familiar with dependency injection, and how that allows us to test a unit (A) of code. However, I'm confused about how to test other units (B and C) which are now possess the external dependency so they can inject it into the original unit (A).
For example, say some class Foo uses an external dependency...
class Foo
{
private ExternalDependency ed;
public int doSomethingWithExternalDependency() {...}
}
And class Bar makes use off Foo...
class Bar
{
public int doSomethingWithFoo
{
Foo f = new Foo();
int x = f.doSomethingWithExternalDependency();
// Do some more stuff ...
return result;
}
}
Now, I know that I can use dependency injection so that I can test Foo, but then how do I test Bar? I guess, I can, again, use dependency injection, but at some point some unit needs to actually create the external dependency; so how do I test that unit?
The examples you provide do not use Dependency Injection. Instead, Bar should use Constructor Injection to get a Foo instance, but there's no point in injecting a concrete class. Instead, you should extract an interface from Foo (let's call it IFoo) and inject that into Bar:
public class Bar
{
private IFoo f;
public Bar(IFoo f)
{
this.f = f;
}
public int doSomethingWithFoo
{
int x = this.f.doSomethingWithExternalDependency();
// Do some more stuff ...
return result;
}
}
This enables you to always decouple consumers and dependencies.
Yes, there will still be a place where you must compose the entire application's object graph. We call this place the Composition Root. It's a application infrastructure component, so you don't need to unit test it.
In most cases you should consider using a DI Container for that part, and then apply the Register Resolve Release pattern.
Keep in mind the difference between unit testing and integration testing. In the former, the dependency would be mocked whereby it provides expected behavior for the purpose of testing the class which consumes the dependency. In the latter, an actual instance of the dependency is initialized to see if the whole thing works end-to-end.
In order to use Dependency Injection, your classes would have their dependencies injected into them (several ways to do that - constructor injection, property injection) and would not instantiate them themselves, as you do in your examples.
Additionally, one would extract the interface of each dependency to help with testability and use the interface instead of an implementation type as the dependency.
class Foo
{
private IExternalDependency ed;
public int doSomethingWithExternalDependency() {...}
public Foo(IExternalDependency extdep)
{
ed = extdep;
}
}
What most people do is use a mocking framework to mock the dependencies when testing.
You can mock any object that the class under test depends on (including behavior and return values) - pass the mocks to the class as its dependencies.
This allows you to test the class without relying on the behavior of its (implemented) dependencies.
In some cases, you may want to use fakes or stubs instead of a mocking framework. See this article by Martin Fowler about the differences.
As for getting all the dependencies, all the way down - one uses an IoC container. This is a registry of all of the dependencies in your system and understands how to instantiate each and every class with its dependencies.
When you unit test a class, you should mock its dependencies, to test your class in isolation -- this is regardless of dependency injection.
The answer to your question about Bar is: yes, you should inject Foo. Once you go down the DI path, you will use it across your entire stack. If you really need a new Foo for every doSomethingWithFoo call, you might want to inject a FooFactory (which you can then mock for testing purposes), if you want a single Bar to use many Foos.
I'd like to stress out that in case of unit testing you should have two separate sets of tests: one for Foo.doSomethingWithExternalDependency and another one for Bar.doSomethingWithFoo. In the latter set create mock implementaion of Foo and you test just doSomethingWithFoo assuming that doSomethingWithExternalDependency works properly. You test doSomethingWithExternalDependency in a separate test set.
Example
I have a repository class (DAL):
public class MyRepository : IMyRepository
{
public void Delete(int itemId)
{
// creates a concrete EF context class
// deletes the object by calling context.DeleteObject()
}
// other methods
}
I also have a service class (BLL):
public class MyService
{
private IMyRepository localRepository;
public MyService(IMyRepository instance)
{
this.localRepository = instance;
}
public void Delete(int itemId)
{
instance.Delete(itemId);
}
// other methods
}
Creating a unit test for MyRepository would take much more time than implementing it, because I would have to mock Entity Framework context.
But creating a unit test for MyService seems nonsense, because it only calls into Repository. All I could check is to verify if it did actually call repository Delete method.
Question
How would you suggest to unit test these pair of Delete methods. Both? One? None? And what would you test?
Yes, I would definitely write a unit test for the Service Layer. The reason for this is because, you're not just testing that your implementation works now, but you're also testing that it will continue to work in the future.
This is a vital concept to understand. If someone comes along later on and changes your ServiceLayer, and there's no unit test, how can you verify that the functionality continues to work?
I would also write tests for your DAL, but I would put those in a separate assembly called DataTests or something. The purpose here is to isolate your concerns across assemblies. Unit Tests shouldn't be concerned with your DAL, really.
Yes, both.
IMyRepository mock = ...;
// create Delete(int) expectation
MyService service = new MyService(mock);
service.Delete(100);
// Verify expectations
Your Delete method right now might only call the Delete method on the repository, but that doesn't mean it always will. You want to have unit tests for this partly to verify it behaves correctly and partly as way of defining your specifications of how the repository is to work.
You also aught to have a test that verifies that the constructor will throw an exception if the repository is null. You might also have other validation to do here in this method such as non-negative ID's, or non-zero id. Maybe that doesn't happen here, make it part of the specifications by creating tests that verify the expected behaviors.
They seem trivial but I can all but guarantee it will change one day and your expectation and specifications may not be verified.
Create the test for the Service. Currently all it does is to call into the Repository Delete method; however, you shouldn't care about that. What if later something happens and the functionality becomes much more complicated? Don't you want to have unit test code that will assure you that the functionality is still working as expected?
If you're exposing your Delete through your Service, you're expecting it to have an effect. Write a Unit Test to test that effect. Depending on your particular needs, I'd say you might not need to have a test on the Repository Delete, particularly if that functionality is getting exercised as part of your Service Delete functionality, but it really all depends on what level of coverage you're trying for.
Also, if you had created this code with TDD, you would have had a test. It actually matters whether people can call Delete through your service, so you actually have to test it.
In my opinion you need to test both. Maybe you can do the creation EF context class in a seperate factory that can be tested more easy and mock the context class for the MyRepository tests. That will be more easy and using a factory for creating a context calls seems to be quiet useful for me.