How do I use GMock with dependency injection? - c++

I have a class which carries a couple of dependencies which I'd like to mock using Google Mocks, in order to test the class with Google Test.
Simplified, I have the following1:
template<typename TDep>
class SUT {
private:
TDep dependency;
public:
explicit SUT(const TDep& dep) : dependency(dep) { }
SUT(const SUT& other) : dependency(dep.other) { }
// some methods that use the dependency
}
I also have an interface for the dependency,
class IDependency {
public:
virtual double calculateCoolStuff(double) const = 0;
virtual ~IDependency() { };
}
and a mock object
class MockDependency {
public:
MOCK_CONST_METHOD1(calculateCoolStuff, double(double));
};
However, when I try to compile something like
MockDependency mock;
SUT sut(mock);
I get errors stating error: use of deleted function MockDependency(const MockDependency&), i.e. there is no copy-constructor of the mocked object. I found this discussion on Google Groups which basically ends in making mock objects non-copyable, but allowing the user to add a copy constructor and define copy behavior manually. Very well:
class MockDependency {
public:
MockDependency(const MockDependency& other) { }
MOCK_CONST_METHOD1(calculateCoolStuff, double(double));
};
Now my code compiles, but if I run something like
MockDependency mock;
SUT sut(mock);
EXPECT_CALL(mock, calculateCoolStuff(2.0)).WillRepeatedly(Return(3.0));
sut.doStuff(); // Calls calculateCoolStuff
in a test, I get an error stating that the call was never set up. In other words, the instance mock which I can use to setup expectations, is no longer the same as the instance on SUT used for calculations. This makes testing with GMock and DI difficult, to say the least...
What is the best solution to this?
1) Yes, I'm using poor man's DI. Not the topic of this conversation...

You can use dependency injection with references by ensuring that your class member is a reference:
template<typename TDep>
class SUT {
private:
TDep& dependency; // Reference
// etc.
}
Note that you no longer need a copy constructor on MockDependency. As a rule, you need access to all instances of mock objects being used by your SUT to set up expectations on them.

Related

Mocking External Dependency object created inside a function without dependency injection in c++

I am trying to write unit tests in C++ and am facing an issue with creating mock objects for an external dependency using Fakeit. So we have a class similar to the following:
class A
{
int test_method()
{
B obj;
return obj.sendInt()
}
};
class B
{
int sendInt()
{
return 5;
}
};
Now let's say I want to write a unit test for test_method() of class A. When we call obj.sendInt() I want to mock it and return a different value. I tried using fakeit but was not able to arrive at a solution.
I know this will be solved if we try to do a dependency injection of B via constructor or in setter methods, but I don't want to do it as it would take some refactoring in existing consumers of A.
For a similar scenario in Java, I would use PowerMockito and achieve the same using PowerMockito.whenNew
B mock = Mockito.mock(B.class);
PowerMockito.whenNew(B.class).withAnyArguments().thenReturn(mock);
Mockito.when(mock.test()).thenReturn(2);
A obj=new A();
assertEquals(obj.test(), 2);
The easiest way would be to use dependency injection. I don't think there's anything similar to PowerMockito for C++ (e.g. it's impossible to mock static methods/functions in a similar manner as PowerMockito allows for java).
If the issue is only with the dependency injection via ctor or setter methods, consider using hi-perf dependency injection, i.e. inject mock using templates.
If the class A cannot be modified at all but you own the class B, consider moving class B to a separate static library: one for production (say, libBprod) and one for testing (libBtest). In production you can link against the libBprod and in tests against libBtest. In libBtest, you can make class B a singleton under the hood. This is quite a lot of work though.
If both class A and class B cannot be modified, then I'm out of ideas - you need to refactor some part of the code somehow.
I moved the code which initializes B and invokes its method to a private method and mocked this private method using gmock
class A
{
int test_method()
{
return getBValue();
}
int getBValue()
{
B obj;
return obj.sendInt()
}
}
My Test Method looks like,
Class MockA :: A
{
public:
MOCK_METHOD(int,getBValue,(),override);
}
TEST_CASE("Test1")
{
MockA mock;
ON_CALL(mock, getBValue()).WillByDefault(Return(10));
REQUIRE(mock.test_method()==10);
}

Mocking a parameterized constructor using powermockito

Consider the code given below:
#Override
public void A() {
objectA = objectB.B();
objectA.C(someValue);
objectC = new constructor(objectA,callback());
//Rest of the code
}
}
public Callback callback() {
return new callback() {
#Override
public void someMethod(someArgument) {
//some Code
}
};
}
I am trying to write a unit test case where:
the call objectB.B() has to be mocked
the call to the constructor has to be mocked
This is what I have done using Mockito and Powermockito:
#InjectMocks
ClassBeingTested testObject;
#Mock
ClassB objectB;
#Mock
ClassC objectC;
#Before()
public void setup() {
when(objectB.B()).thenReturn(new ObjectA("someValue"));
whenNew(objectC.class).withArguments(any(),any()).thenReturn(objectC);
}
#Test()
public void testMethod() {
testObject.A();
}
The first mock successfully works but the second mock using whenNew fails with the following error:
org.powermock.reflect.exceptions.ConstructorNotFoundException: No constructor found in class 'ClassC' with parameter types: [ null ]
If I use withArguments(objectA, callback()) where I have the implementation of callback in my test class, the actual constructor is called.
I want to mock the constructor call and restrict the call to the actual constructor. How can I do that?
I can not edit the code design since that is out of my scope.
In short, you get the error due to usage of 2 generic any() matchers.
When you use .withArguments(...) and set both as any() it implies
.withArguments(null, null) (since any() may match pretty much anything including nulls) which folds eventually as a single null and reflection api (which PowerMock heavily relies on) fails to discover a suitable constructor for ClassC(null).
You may check out the source of org.powermock.api.mockito.internal.expectation.AbstractConstructorExpectationSetup<T>
source that does the job
To fix up the issue consider using either .withAnyArguments() if you do not care of param types and stubbing all available constructors OR specify more concrete types while using any() like so
whenNew(ClassC.class).withArguments(any(ClassA.class), any(Callback.class))

Using googlemock with fake impls of non-virtual functions

I've got legacy code with some unit tests based on googlemock framework. While I was trying to extend the unit tests with some new scenarios I met the following problem:
class D
{
public:
void pubMethod1();
int pubMethod2();
// There are pretty much non-virtual methods, both public and private
...
protected:
uint method3();
void method4();
...
// Some class members are here
};
class SUT
{
public:
...
protected:
D _dep;
};
The SUT class (software under test) should be tested, its implementation is defined in file sut.cpp. The SUT depends on D class, whose implementation is in file d.cpp. To decrease linker dependencies I would not like to add d.cpp to the test, so there are many 'undefined symbol' errors against the D's members when I link the test. To eleminate the errors and provide predictable behaviour I'm going to create fake implementations for the D's methods in my test. However I'm still not able to use it with all the googlemock's power until the D's methods are virtual.
I like an idea to use WillOnce, AtLeast, WillRepeatedly, Invoke, etc. functions from the googlemock framework, because it makes unit test creation easier. The problem is that I don't like an idea to change the D's interface, turning its methods into virtual ones. Is it possible to use the googlemock functions with the fake implementations I'm going to create for the D's methods?
NOTE: I already considered the solution with templated SUT class, however I'm wondering if other solution exists.
First of all - the best would be to redesign your SUT class to have D injected via some abstract interface. Because the workaround I am describing below is really tricky - so not so easy to maintain and understand in future...
If you are going to make fake implememtation of your D class in UT target - then you can make Mock class for D: DMock. This DMock will not be related to D - not derived from it - but it needs to be paired with real/fake D objects.
So - see the example:
Create DMock - that imitates the D interface (note that you should mock only public functions - because your SUT uses only public ones):
class DMock
{
public:
MOCK_METHOD0(pubMethod1, void ());
MOCK_METHOD0(pubMethod2, int ());
};
Pair your real (but fake) D objects with DMock objects - something like this:
class DMockRepo
{
public:
// for UT
void addMockToUse(DMock* dMock) { freeMock.push_back(dMock); }
// for implementing D fake methods
DMock& getMock(D* original)
{
// TODO: use more sophisticated way to add mock to map...
if (not usedMock[original])
{
usedMock[original] = freeMock.front();
freeMock.pop_front();
}
return *useddMock[original];
}
static DMockRepo& getInstance() { return instance; } //singleton
private:
DMockRepo() {} // private
static DMockRepo instance;
std::map<D*,DMock*> usedMock;
std::deque<DMock*> freeMock;
};
Use mock to create fake implementation of public methods of D class:
void D::pubMethod1()
{
DMockRepo::getInstance().getMock(this).pubMethod1();
}
//
Non-public methods are irrelevant - so do whatever you like...
And use DMockRepo to set expectation on your D objects:
TEST(Usage,Example)
{
DMock dMock;
DMockRepo::getInstance().addMockToUse(&dMock);
SUT sut; // you should know how many D objects SUT needs - I assume just one
EXPECT_CALL(dMock, pubMethod1());
sut.doSomethingThatCallsDpubMethod1();
}

Why it doesn't throw any exceptions when attempting to mock a singleton using either Mockito or PowerMock?

I have a singleton class "Fake"
public class Fake{
private static Fake instance;
private Fake(){
}
public static Fake getInstance(){
if(instance == null)
instance = new Fake();
return instance;
}
public String getTestString(String s){
return s;
}
}
I want to create a mock Fake object so I can mock method calls to non-static method getTestString(String s). I have used both Mockito and PowerMock (Mockito extension) in the way that comes below.
//using Mockito
Fake fake = Mockito.mock(Fake.class);
//using PowerMock
Fake fake = mock(Fake.class);
In both cases, as the code is attempting to mock a singleton (with a private constructor) I expect an exception to occur, but it just normally works. I suspect that there is something wrong with it and maybe it is not working actually.
Mocking doesn't instantiate a class, it creates a proxy for it. Having a private constructor or a constructor with parameters doesn't make a difference.
The behavior you're seeing is normal and expected.
By using mocking, it means you are not testing the class itself, but want to dictate the behavior of the class so that it performs in an arbitrary way you want.
The mock is only useful when you are trying to test some other class which has a dependency on the class being mocked.
In your case, if you want to test the class being a Singleton, you should test on an REAL instance rather than a mock of the class.
Moreover, your method:
public String getTestString(String s){
return s;
}
always returns the String you passed in, this does not look right to me and not sure what you are trying to do here.
Because you're not ever creating an actual instance of Fake, only an instance of a proxy that fulfills Fake's interface, the mock is succeeding.
Separately, regardless of whether Fake's constructor is private, Mockito cannot stub or verify static methods. If your real goal is to override getInstance, you'll need to do so with PowerMock.
However, by adjusting your system-under-test, you can skip Powermock and test your method with Mockito directly:
public class YourSystemUnderTest {
public int yourMethodUnderTest() {
return yourMethodUnderTest(Fake.getInstance());
}
/** Visible for testing. */
int yourMethodUnderTest(Fake fake) {
// ...
}
}
public class YourTest {
#Test
public void yourMethodShouldReturn42() {
Fake fake = mock(Fake.class);
YourSystemUnderTest systemUnderTest = new YourSystemUnderTest();
assertEquals(42, systemUnderTest.yourMethodUnderTest(fake));
}
}
It's even easier if YourSystemUnderTest takes a Fake instance in its constructor, because then you can set up the reference to the Fake instance once in a setUp() or #Before method.

Howto mix TDD and RAII

I'm trying to make extensive tests for my new project but I have a problem.
Basically I want to test MyClass. MyClass makes use of several other class which I don't need/want to do their job for the purpose of the test. So I created mocks (I use gtest and gmock for testing)
But MyClass instantiate everything it needs in it's constructor and release it in the destructor. That's RAII I think.
So I thought, I should create some kind of factory, which creates everything and gives it to MyClass's constructor. That factory could have it's fake for testing purposes. But's thats no longer RAII right?
Then what's the good solution here?
You mock it the same way you'd mock any other class. Have the RAII class' constructor take care of it.
class MyInterface
{
virtual void MyApiFunction(int myArg)
{
::MyApiFunction(myArg);
}
};
class MyRAII : boost::noncopyable //Shouldn't be copying RAII classes, right?
{
MyInterface *api;
public:
MyRAII(MyInterface *method = new MyInterface)
: api(method)
{
//Aquire resource
}
~MyRAII()
{
//Release resource
delete api;
}
};
class MockInterface : public MyInterface
{
MOCK_METHOD1(MyApiFunction, void(int));
};
TEST(Hello, Hello)
{
std::auto_ptr<MockInterface> mock(new MockInterface);
EXPECT_CALL(*mock, ....)...;
MyRAII unitUnderTest(mock.release());
}