Unit testing classes that use dagger 2 to create objects - unit-testing

Let's say I have a dagger 2 module as follows,
#Module
interface Creator {
MyClass create();
}
and I am using it to create an instance of MyClass
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
It seems to me that I cannot effectively test the doSomething method in Instantiator because I cannot provide a mock for MyClass.
Am I wrong? If not are we supposed to use Dagger instantiation sparingly?

You are correct in saying that it is hard to test use of a Component injector, since this is a static method. But harder than what? Here is the same method using instantiation:
class Instantiator {
void doSomething(){
MyClass clazz = new MyClass();
// do things with clazz
}
}
still hard to test, right?
The point is to use as few Component (injectors) as possible and to pass in dependencies in the constructor for your objects. Dagger 2 makes resolving the dependencies in the constructor easy. This thereby makes testing easy since you can pass in mock object in a constructor.
Let's refactor the code you wrote to be testable. Assume that MyClass contains a single method, fireLazers() that you want to test is being invoked inside Instantiator's doSomething() method:
public class DoerOfSomething {
private final MyClass myClass;
#Inject
public DoerOfSomething(MyClass myClazz) {
this.myClass = myClazz;
}
public void doSomething() {
myClass.fireLazers();
}
}
Now you can write a test like this using a mock object:
public void DoerOfSomethingTest {
//mocks
MyClass mockMyClass;
//system under test
DoerOfSomething doerOfSomething;
#Before
public void setUp() {
mockMyClass = Mockito.mock(MyClass.class);
}
#Test
public void whenDoSomething_thenInteractsWithMyClass() {
//arrange
doerOfSomething = new DoerOfSomething(mockMyClass);
//act
doerOfSomething.doSomething();
//assert
verify(mockMyClass).fireLazers();
}
}
Of course, you will now need to inject DoerOfSomething into the top level class where you are injecting, but now you can be certain that the object you are injecting is functioning as expected because it is testable. Your code for using Dagger looks a bit unusual but I'll use your idioms for the sake of parity between the question and the answer.
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}

Related

references are a pain for my mocks in TDD

I am new with c++/tdd, embraced gtest/gmock, and fell in love.
One thing kind of puzzles me though. Are reference pointers really the way to go?
I find myself producing a lot of boiler plate injecting all mocks (even when I don't have any business mocking that behavior).
Example:
namespace
{
class set_configuration_command_tests : public testing::Test
{
protected:
void SetUp() override
{
_uart_peripheral = new uart8_peripheral_mock();
_uart = new uart8_mock(*_uart_peripheral);
_logger = new logger_mock(*_uart);
_mqtt_client = new mqtt_client_mock(*_logger);
_set_configuration_command = new set_configuration_command(*_mqtt_cient);
}
void TearDown() override
{
delete _set_configuration_command;
}
uart8_peripheral_mock *_uart_peripheral;
uart8_mock *_uart;
logger_mock *_logger;
mqtt_client_mock *_mqtt_cient;
set_configuration_command *_set_configuration_command;
};
TEST_F(set_configuration_command_tests, execute_update_configuration)
{
// arrange
// act
// assert
}
}
What I rather did here, is create my sut as
_mqtt_client = new mqtt_client_mock(nullptr); // will not compile of course
_set_configuration_command = new set_configuration_command(*_mqtt_cient);
All the other mocks, I don't need in this case.
Is this the drawback of using reference pointers? Or is there a better approach I should follow?
Found a better alternative. Providing interfaces (pure virtual classes) heavily reduces the need to provide an entire tree of mocks.
e.g
class flash_api : public iflash_api
{
public:
flash_api(iflash_peripheral &flash_peripheral) : _flash_peripheral(flash_peripheral)
{
}
virtual ~flash_api()
{
}
}
Before my mock inherited from flash_api directly. When I gave this class an interface too (`iflash_api') I can let my mock inherit from iflash_api, which gives me a parameter-less constructor.
class flash_api_mock : public iflash_api
{
public:
flash_api_mock()
{
}
virtual ~flash_api_mock()
{
}
}
Then I can write my unit test based on the mocks I actually want to give behavior.
class set_configuration_command_tests : public testing::Test
{
protected:
void SetUp() override
{
_mqtt_cient = new mqtt_client_mock();
_flash_api = new flash_api_mock();
_set_configuration_command = new set_configuration_command(*_mqtt_cient, *_flash_api);
}
void TearDown() override
{
delete _set_configuration_command;
}
flash_api_mock *_flash_api;
mqtt_client_mock *_mqtt_cient;
set_configuration_command *_set_configuration_command;
};

How to use mocks with a test fixture in GMock?

I have a test fixture in my tests so I don't have to instantiate objects of my class repeatedly, but I'm not sure how to use mocks with it. To put it simply, this is how the class is defined:
class Class1 {
public:
Class1(std::shared_ptr<Class2> class_two);
void doThisThing() { doThatThing(); }
}
class Class2 {
public:
Class2(Class3* class3_ptr);
int doThatThing();
}
(class 1 is constructed using a shared pointer to class 2. Class 2 is constructed with a pointer to class 3. Class 1 calls on a function "doThisThing" which calls Class 2's function doThatThing.)
I need to create a mock for doThatThing() (and the rest of Class2's functions), but can't figure out how to pass the mock object to Class 1. Here is what I have so far in my testing code:
class TestClass1 : public ::testing::Test {
TestClass1(){
//Construct instance of Class1 and store as member variable
std::shared_ptr<Class3> class_three = std::make_shared<Class3>();
std::shared_ptr<Class2> class_two = std::make_shared<Class2>((Class3*)class_three.get());
class_one = new Class1(class_two);
};
Class1* class_one;
}
MockClass2 : public Class2 {
MOCK_METHOD0(doThatThing, int());
}
TEST_F(TestClass1, doThatThingTest){
MockClass2 mockObj;
**THIS IS WHERE I'M STUCK. How do I get that mockObj into my TestClass1 Fixture? As of now, it is calling the actual function, not the mock***
class_one->doThatThing();
EXPECT_CALL(mockObj, doThatThing());
}
I had to abstract and simplify the actual code, so I hope the above makes sense.
Assuming that your MockClass2 works, you should try something like the following:
Here you should override the functions SetUp that is called right before every call of a test function to prepare your test data. And override TearDown that is called after every call of a test function to clean up test data.
struct TestClass1 : public ::testing::Test
{
void SetUp() override
{
class_two_mock = std::make_shared<MockClass2>();
class_one = std::make_unique<Class1>(class_two_mock);
}
void TearDown() override
{
class_one.reset();
class_two_mock.reset();
}
std::shared_ptr<MockClass2> class_two_mock
std::unique_ptr<Class1> class_one;
};
In the test function you must declare your expectations before something is executed.
TEST_F(TestClass1, doThatThingTest)
{
EXPECT_CALL(*class_two_mock, doThatThing());
class_one->doThatThing();
}
You may need an interface for Class2. The code here is not tested.

Java Mockito - How to test a method which is calling a method in the same class as well as a method from other class?

I have the code structure like this. Method methodToTest in ClassA is calling a method in ClassA as well well as a method in ClassB
public class ClassA {
#Autowired
ClassB classB;
public void methodToTest() {
Object c = methodInA();
Object d = classB.methodInB(c);
}
public Object methodInA() {
//do something
}
}
public class ClassB {
public Object methodInB(Object obj) {
//do something
}
}
I was trying to mock both calls i.e. call to methodInA and to methodInB
Following is the unit-test code
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class ClassATest {
#InjectMocks
ClassA classA;
#Mock
ClassB classB;
#Spy
ClassA classASpy;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
//Test method in ClassA
#Test
public void testMethodInA() {
Object mockObjA = mock(Object.class);
Object mockObjB = mock(Object.class);
doReturn(mockObjA).when(classASpy).methodInA();
when(classB.methodInB(mockObjA)).thenReturn(mockObjB);
classA.methodToTest();
//assertions
}
}
On running the test, Object c is null but I want it to be equal to mockObjA.
I tried invocation with classASpy.methodToTest() also from the test. But then it gives NullPointerException at line Object d = classB.methodInB(c) in methodToTest().
What will be the correct way to test such scenario?
When you are invoking methodToTest you are testing the unit ClassA. It doesn't make much sense to alter the unit under test by mocking something of that unit. Because then you would test something completely different then ClassA.
What you should do is to test that classB.methodInB is invoked with the correct argument. You do this by using an ArgumentCaptor for the argument of invocation classB.methodInB.
ArgumentCaptor<Object > argument = ArgumentCaptor.forClass(Object .class);
verify(mockObjB).methodInB(argument.capture());
Object capturedArgument = argument.getValue();
Then you make assertions on capturedArgument that verify that ClassA.methodInA worked correctly.

Mockito: verify the captured object's method is called

I am using Mockito to write a simple unit test. I have a smiple abstract class which implements Runnable:
public abstract class MyRunnable implements Runnable {
#Override
public void run() {
doTask();
}
public abstract void doTask();
}
Then, a function under test uses MyRunnable:
public class MyService {
public void something() {
executor.execute(new MyRunnable() {
#Override
doTask() {
…
}
});
}
}
My test case, I want to test doTask() has run :
#Test
public void testSomething() {
…
ArgumentCaptor<MyRunnable> myCaptor = ArgumentCaptor.forClass(MyRunnable.class);
verify(mockMyService).something(myCaptor.capture());
// get what has been captured
MyRunnable myRunnable = myCaptor.getValue();
//verify doTask() has run , but got ERROR.
verify(myRunnable).doTask();
}
My test case throw the following error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type and is not a mock!
The error complains that verify() only accept mocked object. Then, how can I verify/test that the captured MyRunnable object has run doTask() with Mockito?
If you have control over your codebase, you can make your code testable with Mockito by moving any code that uses the new keyword into a separate Factory class like so...
public class MyService {
private MyRunnableFactory = factory;
public MyService(MyRunnableFactory factory) {
this.factory = factory;
}
public void something() {
executor.execute(factory.createInstance());
}
}
Then your test can simply inject a Mock of the factory which you can verify its behaviour/interactions
#Mock MyRunnableFactory factory;
#Mock MyRunnable myRunnable;
#Test
public void testSomething() {
when(factory.createInstance()).thenReturn(myRunnable);
// method under test
MyService service = new MyService();
service.something();
verify(myRunnable).doTask();
}
I use a rule of thumb that classes that creates objects, shouldn't have any business logic, so you don't have these testing headaches. This is essentially the Single Responsibilty Principal
You can't do this with Mockito because MyRunnable is created by the code under test. But you may have a look at PowerMock because it allows you to mock the constructor: https://github.com/jayway/powermock/wiki/MockConstructor

Using RhinoMocks, how can I assert that one of several methods was called?

Consider the following service interfaces:
public interface IServiceA
{
void DoSomething(string s);
void DoSomething(string s, bool b);
}
public interface IServiceB
{
void DoSomething();
}
The implementation of IServiceB depends on IServiceA like this:
public class ServiceB : IServiceB
{
private IServiceA _serviceA;
public ServiceB(IServiceA serviceA)
{
_serviceA = serviceA;
}
public void DoSomething()
{
_serviceA.DoSomething("Hello", true);
}
}
Ie. the dependency is injected in the constructor.
Now consider a unit test for the DoSomething() method. I wish to assert that one of the overloaded DoSomething-methods in IServiceA is called, but following a general principle that unit tests shouldn't know too much about the internal workings of the method being tested, I wish to be agnostic about which of the two overloads is called. Consider the following unit test:
[TestFixture]
public class ServiceBTests
{
[Test]
public void DoSomething_CallsServiceA()
{
var serviceAMock = MockRepository.GenerateMock<IServiceA>();
var service = new ServiceB(serviceAMock);
service.DoSomething();
// Problem: How to check if EITHER:
serviceAMock.AssertWasCalled(s => s.DoSomething(Arg<String>.Is.NotNull, Arg<bool>.Is.Anything));
// OR:
serviceAMock.AssertWasCalled(s => s.DoSomething(Arg<String>.Is.NotNull));
}
}
How can I assert that either one or the other of the two methods was called?
You could manually set a boolean flag like so:
[TestFixture]
public class ServiceBTests
{
[Test]
public void DoSomething_CallsServiceA()
{
var serviceAMock = MockRepository.GenerateMock<IServiceA>();
bool called = false;
serviceAMock.Stub(
x => x.DoSomething(Arg<String>.Is.NotNull, Arg<bool>.Is.Anything))
.WhenCalled(delegate { called = true; });
serviceAMock.Stub(x => x.DoSomething(Arg<String>.Is.NotNull))
.WhenCalled(delegate { called = true; });
var service = new ServiceB(serviceAMock);
service.DoSomething();
Assert.IsTrue(called);
}
}
I don't think this very useful though. Unit tests are concerned with anything that is observable from outside of the component boundaries. Method calls to mocks are part of that. In other words, it is OK if you test for a specific overload being called. After all, there must be a reason why you use that overload and not the other one.
If you really want the unit test to remain ignorant of the implementation, you wouldn't be allowed to assert method calls on mocks at all. That would be a severe restriction on your ability to write tests.