Using GoogleMock to mock an instance created by code under test - c++

I have create an interface (here's an example):
class DataStream
{
virtual std::string read(std::string terminator) = 0;
virtual size_t write(std::string data) = 0;
};
For which there exists a concrete implementation, such as:
class SerialDataStream : public DataStream
{
public:
// NOTE: This constructor will throw an exception if the
// serial port cannot be opened.
SerialDataStream(string port, int baudrate);
std::string read(std::string terminator);
size_t write(std::string data);
}
And the interface is used, for example:
class SomeThing
{
public:
SomeThing(std::shared_ptr<DataStream> stream);
}
Using GoogleMock, testing the SomeThing class is fairly straight forward, all you need to do is create a mock implementation for the interface, for example:
class MockDataStream : public DataStream
{
public:
MOCK_METHOD1(read, size_t(std::vector<uint8_t>&));
MOCK_METHOD1(write, size_t(std::vector<uint8_t>&));
}
Where the test would look something like this:
std::shared_ptr<MockDataStream> mock_stream(nullptr);
mock_stream = std::make_shared<MockDataStream>();
EXPECT_CALL(*mock_stream, write("START")).Times(AtLeast(1));
EXPECT_CALL(*mock_stream, read("\n")).Times(AtLeast(1));
SomeThing some_thing = SomeThing(mock_stream);
Which is pretty cool as it easily allows me to unittest how the SomeThing class uses the DataStream interface.
However, there also exists some code whose job it is to create new (concrete) DataStream objects and I'm finding using GoogleMock to test this a little more tricky. For example, here is a snippet of some code that needs to be tested:
std::shared_ptr<DataStream> datastream(nullptr);
// Try and open the serial port:
try
{
std::shared_ptr<SerialDataStream> serialstream =
std::make_shared<SerialDataStream>("/dev/tty99", 115200);
}
catch (...)
{
// Returns a nullptr
return datastream;
}
// Check if there is a known device on the other end:
datastream = std::static_pointer_cast<DataStream>(serialstream);
if (!device_is_connected(datastream))
{
datastream = nullptr;
}
return datastream;
I'm struggling to find an effective method to test this code with GoogleMock:
I would like to mock the constructor (of SerialDataStream) so it throws an exception and the failure path is executed as expected.
I would like to test the successful path where the private API "device_is_connected" uses the newly created datastream object.
Is it the case that I have no option other than to create a fake SerialDataStream implementation and use dependency injection to test the code which creates concrete DataStream objects?
If this is the case, I'll just have to make the API "device_is_connected" public so I can simply test it with a mock implementation of the interface (as above) to test, for example:
datastream.write("DISCOVER");
string response = datastream.read("\n");
if (discovery_ok(response))
{
// do stuff
}
I'm fairly certain I've answered my own question and will have no option but to fake the SerialDataStream class and use dependency injection, and make private APIs public and simply test them via GoogleMock, but I'm open to suggestions if there's a better way I could/should be doing things here.

Looking at the code snipped you provided, I found myself asking:
What exactly should the function do? It seems like it
(1) creates a SerialDataStream and
(2) checks if a device is connected.
You may could break the function into two (individually testable) parts.
Still there is the question on how to handle the std::shared_ptr<SerialDataStream> serialstream = std::make_shared<SerialDataStream>("/dev/tty99", 115200); - at some point you will need to tackle the (hidden) new there.
And I agree with you - dependency injection might be the solution there. Turning whatever class or function ends up responsible for creating into a template class/function would allow to write you (e.g.)
template<typename T>
std::shared_ptr<DataStream> createDatastream()
{
std::shared_ptr<DataStream> datastream(nullptr);
std::shared_ptr<T> datastream = std::make_shared<T>("/dev/tty99", 115200);
return datastream;
}
And then instantiate the class/function with SerialDataStream in your application, while using a MockDataStream to test the function(s).

Related

Spock - How to work with repeated interactions

For few test cases I'm trying to follow a DRY principle, where only the interactions are different with same test case conditions. I'm not able to find a way to implement multiple methods in the interaction { } block.
As mentioned in http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_explicit_interaction_blocks, I'm using interaction { } in the then: block like below:
Java Code:
// legacy code (still running on EJB 1.0 framework, and no dependency injection involved)
// can't alter java code base
public voidGetData() {
DataService ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset() // happy path scenario; missing a null check
// other code
}
// other varieties of same code:
public voidGetData2() {
ItemEJB tmpItem = new ItemEJB();
ItemEJB item = tmpItem.findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
public voidGetData3() {
ItemEJB item = new ItemEJB().findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
Spock Test:
def "test scene1"() {
given: "a task"
// other code ommitted
DataService mockObj = Mock(DataService)
when: "take action"
// code omitted
then: "action response"
interaction {
verifyNoDataScenario() // How to add verifyErrorScenario() interaction to the list?
}
}
private verifyDataScenario() {
1 * mockObj.findByOffset(5) >> mockObj // the findByOffset() returns an object, so mapped to same mock instance
1 * mockObj.getOffset() >> 200
}
private verifyErrorScenario() {
1 * mockObj.findByOffset(5) >> null // the findByOffset() returns null
0 * mockObj.getOffset() >> 200 // this won't be executed, and should ie expected to throw NPE
}
The interaction closure doesn't accept more than one method call. I'm not sure if it's design limitation. I believe more can be done in the closure than just mentioning the method name. I also tried interpolating the mockObj as a variable and use data pipe / data table, but since it's referring the same mock instance, it's not working. I'll post that as a separate question.
I ended up repeating the test case twice just to invoke different interaction methods. Down the line I see more scenarios, and wanted to avoid copy & paste approach. Appreciate any pointers to achieve this.
Update:
Modified shared java code as the earlier DataService name was confusing.
As there's no DI involved, and I didn't find a way to mock method variables, so I mock them using PowerMockito, e.g. PowerMockito.whenNew(DataService.class).withNoArguments().thenReturn(mockObj)
Your application code looks very strange. Is the programming style in your legacy application really that bad? First a DataService object is created with a no-arguments constructor, just to be overwritten in the next step by calling a method on that instance which again returns a DataService object. What kind of programmer creates code like that? Or did you just make up some pseudo code which does not have much in common with your real application? Please explain.
As for your test code, it also does not make sense because you instantiate DataService mockObj as a local variable in your feature method (test method), which means that in your helper method mockObj cannot be accessed. So either you need to pass the object as a parameter to the helper methods or you need to make it a field in your test class.
Last, but not least, your local mock object is never injected into the class under test because, as I said in the first paragraph, the DataService object in getData() is also a local variable. Unless your application code is compeletely fake, there is no way to inject the mock because getData() does not have any method parameter and the DataService object is not a field which could be set via setter method or constructor. Thus, you can create as many mocks as you want, the application will never have any knowledge of them. So your stubbing findByOffset(long offset) (why don't you show the code of that method?) has no effect whatsoever.
Bottom line: Please provide an example reflecting the structure of your real code, both application and test code. The snippets you provide do not make any sense, unfortunately. I am trying to help, but like this I cannot.
Update:
In my comments I mentioned refactoring your legacy code for testability by adding a constructor, setter method or an overloaded getData method with an additional parameter. Here is an example of what I mean:
Dummy helper class:
package de.scrum_master.stackoverflow.q58470315;
public class DataService {
private long offset;
public DataService(long offset) {
this.offset = offset;
}
public DataService() {}
public DataService findByOffset(long offset) {
return new DataService(offset);
}
public long getOffset() {
return offset;
}
#Override
public String toString() {
return "DataService{" +
"offset=" + offset +
'}';
}
}
Subject under test:
Let me add a private DataService member with a setter in order to make the object injectable. I am also adding a check if the ds member has been injected or not. If not, the code will behave like before in production and create a new object by itself.
package de.scrum_master.stackoverflow.q58470315;
public class ToBeTestedWithInteractions {
private DataService ds;
public void setDataService(DataService ds) {
this.ds = ds;
}
// legacy code; can't alter
public void getData() {
if (ds == null)
ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset();
}
}
Spock test:
Now let us test both the normal and the error scenario. Actually I think you should break it down into two smaller feature methods, but as you seem to wish to test everything (IMO too much) in one method, you can also do that via two distinct pairs of when-then blocks. You do not need to explicitly declare any interaction blocks in order to do so.
package de.scrum_master.stackoverflow.q58470315
import spock.lang.Specification
class RepeatedInteractionsTest extends Specification {
def "test scene1"() {
given: "subject under test with injected mock"
ToBeTestedWithInteractions subjectUnderTest = new ToBeTestedWithInteractions()
DataService dataService = Mock()
subjectUnderTest.dataService = dataService
when: "getting data"
subjectUnderTest.getData()
then: "no error, normal return values"
noExceptionThrown()
1 * dataService.findByOffset(5) >> dataService
1 * dataService.getOffset() >> 200
when: "getting data"
subjectUnderTest.getData()
then: "NPE, only first method called"
thrown NullPointerException
1 * dataService.findByOffset(5) >> null
0 * dataService.getOffset()
}
}
Please also note that testing for exceptions thrown or not thrown adds value to the test, the interaction testing just checks internal legacy code behaviour, which has little to no value.

Google Mock for NonVirtual and Private Functions

I'm attempting to write Mocks for Private / Non Virtual / Static functions and come across a way to do the same.
Here is how it looks like..
Lets assume that I have a class A which needs to be mocked and used inside class UsingA. The definition of both classes looks like
class A
{
friend class UsingA;
int privateFn() {}
public:
int nonVirtual() {}
};
// The UsingA class
class UsingA {
A &a1;
public:
UsingA(A & _a1) : a1(_a1) {}
int CallFn() {
return a1.nonVirtual();
}
int CallFn2() {
return a1.privateFn();
}
};
I know that Mocks are meant for generating the behavior of the class and while creating Mocks, we need to derive from the original class.
However, to Mock the behavior I decided not to derive from the original class, instead comment the class A and generate a Mock class with the same Name i.e class A.
Here is how my mock class looks like
// Original class A is commented / header file removed
class A {
public:
MOCK_METHOD0(nonVirtual, int());
MOCK_METHOD0(privateFn, int());
};
And my tests are usual mock tests
TEST(MyMockTest, NonVirtualTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, nonVirtual())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn();
EXPECT_EQ(retVal,100);
}
TEST(MyMockTest, PrivateTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, privateFn())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn2();
EXPECT_EQ(retVal,100);
}
And everything works fine and I'm able to test UsingA by this mock.
Question is.
This looks easier and serves the purpose, still I haven't seen this kind of examples while browsing for google mock examples. Is there anything that would go wrong if I do this?
Honestly, I didn't find any.
NOTE: Folks, I'm using friend for demonstration only. My actual use case is totally different. Thanks
The wrong is that you are not testing real code, because of that:
comment the class A
generate a Mock class with the same name
These operations alter the code under test.
An example what can go wrong:
Change return type: long nonVirtual in Mock - previously was int
Test that on, let say, nonVirtual() == 0xFF'FFFF'FFFF (which is bigger than INTMAX) some action is being done
Forget to change in real A - so real UsingA have branch that is tested but never reachable in real code
An example code:
class A {
public:
MOCK_METHOD0(nonVirtual, long()); // change
MOCK_METHOD0(privateFn, int());
};
void UsingA::processA()
{
if (a.nonVirtual() > VERY_BIG_NUMBER)
{
throw runtime_error("oops");
}
}
TEST_F(UsingATest, throwOnVeryBigNumber)
{
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VERY_BIG_NUMBER + 1));
ASSERT_THROW(objectUndertTest.processA());
}
But real A did not change - so we test non reachable code in UsingA class:
class A {
public:
int nonVirtual(); // not changed
...
};
The best solution is (in order):
To test in isolation you have to isolate classes - so to use dependency injection (virtual functions etc, base interfaces, etc...) - this is sometimes called London School of TDD
Test both classes A and UsingA w/o any stubbing - test them together in one testcase - thus you test real code - this is called Detroit Shool of TDD
Separate by template code with good restriction on interface - this approach is most similar to yours:
Regarding 3 - you might use something like this:
template <class T = A>
class UsingA {
T &a1;
public:
UsingA(T & _a1) : a1(_a1) {}
long CallFn() {
using ANonVirtualResult = std::invoke_result_t<&T::nonVirtual>;
static_assert(std::is_same<long, ANonVirtualResult>::value);
return a1.nonVirtual();
}
...
};
And in test:
class UsingATest : public ::testing::Test
{
protected:
StrictMock<AMock> aMock;
using ClassUnderTest = UsingA<AMock>;
ClassUnderTest objectUnderTest{aMock};
};
TEST_F(UsingATest, useNonVirtual)
{
const auto VALUE = 123456;
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VALUE));
ASSERT_EQ(VALUE, objectUnderTest.CallFn());
}
You might note that some assumption about A might be tested during compilation as static_assert or via some SFINAE technics (more complicated).
Actually, there are examples with template code in googlemock as workaround for mocking classes w/o virtual functions.
We use your type of using mocks inside a few of our test projects to check callbacks on a larger class that we pass along using dependency injection. In our case, the methods are declared virtual.
In your case, they are not. Your mock implementation would hide the original implementation - if there was any. So I don't think there's an issue here.

Google mock: Mocking parent class?

Assume I have a base class:
class Command {
public:
virtual int8_t Execute();
};
with a definition in the base class cpp.
Additionally, I have a child class:
class SpecificCommand: public Command {
public:
int8_t Execute();
};
With the definition:
int8_t SpecificCommand::Execute() {
doSomeStuff();
Command::Execute();
}
How do I mock Command::Execute() but using a SpecificCommand object for tests?
Maybe something like that:
class SpecificCommandMock : public SpecificCommand
{
public:
MOCK_METHOD0(ExecuteMockedMethod, void());
int8_t Execute() override
{
doSomeStuff()
ExecuteMockedMethod();
}
}
Of course you should use SpecificCommandMock in unit tests and set EXPECT_CALL for ExecuteMockedMethod when class under test is expected to call Execute().
In addition I suppose that something could be wrong in design of the application if you have to do such things.
This should not be possible in the way you are expecting. I.e. gtest cannot just replace the part of your code and instead of:
int8_t SpecificCommand::Execute() {
doSomeStuff();
Command::Execute();
}
execute something like:
int8_t SpecificCommand::Execute() {
doSomeStuff();
}
You operate with macroses mainly which are just wrap your code with some other. So the language limitation still in there.
Some options (which don't affect your Command implementation):
if doSomeStuff is a public - override the Execute() with mock class as proposed by trivelt or do it like official docs suggests with ON_CALL declaration in mock constructor
write DummyCommand.cpp which do nothing and by compilation option build it instead of original one. In cmake it's if-else + add_library/add_executable manipulations.
write mock to the library which uses "network access that can not be tested" and link it instead of original one by compilation option. (if-else + target_link_library or even include manipulations in the cmake)
write mock for the network communication backend (web_server, etc)

Builder pattern - configuration file reading

I'm facing a design problem. I want to separate building objects with a builder pattern, but the problem is that objects have to be built from configuration file.
So far I have decided that all objects, created from configuration, will be stored in DataContext class (container for all objects), because these objects states will be updated from a transmission (so it's easier to have them in one place).
I'm using external library for reading from XML file - and my question is how to hide it - is it better to inject it to concreteBuilder class? I have to notice that builder class will have to create lots of objects and at the end - connect them between each other.
Base class could look like that:
/*
* IDataContextBuilder
* base class for building data context object
* and sub obejcts
*/
class IDataContextBuilder {
public:
/*
* GetResult()
* returns result of building process
*/
virtual DataContext * GetResult () = 0;
/*
* Virtual destructor
*/
virtual ~IDataContextBuilder() { }
};
class ConcreteDataContextBuilder {
public:
ConcreteDataContextBuilder(pugi::xml_node & rootNode);
DataContext * GetResult ();
}
How to implement it correctly? What could be better pattern to build classes from configuration files?
I don't see a problem with that, but maybe you could inject another 'Director' class that receives a specific builder, loads the config files, and produces objects calling the respective builder-subclasses.
What I mean:
class DataContextDirector {
public:
void SetBuilder(IDataContextBuilder* builder);
void SetConfig(const std::string& configFilePath); // or whatever
DataContext* ProduceObject() {
// pseudo-code here:
// myBuilder->setup(xmlNodeOfConfig);
// return myBuilder->GetResult();
}
};

Strategy Design Pattern for handling requests

I need to refactor class, which handles requests. I don't need chain of responsibility, because in compile time I have specified which request is connected to which handler.
My idea is to create one singleton class which is responsible for all logic.
For example it will have pointer to database object and it will handle requests.
There will be interface for HandlerMessage and many class derived from them.
Suppose we have:
class Singleton {
Database db;
int handleMessage(const Request& in, Response& out);
};
int Singleton::handleMessage(const Request& in, Response& out) {
int result = 0;
HandlerMessage* handler;
if(in.type == RequestType::A)
handler = new HandlerA();
else if(in.type == RequestType::B)
handler = new HandlerB();
else
return -1;
result = handler->handle(in, out);
delete handler;
return result;
}
However HandlerMessage needs to use Database and I wonder how to get use them.
I can pass pointer to database as an argument of handle function in HandlerMessage class.
However it seems to me strange, because all time I will pass the same argument. Moreover not all handlers needs to use database.
My question is:
class MessageHandler {
static Database* db;
}
this a good solutions, where I initialized db from MessageHandler class with db from SingeltonClass in Singleton constructor?
Or it is better to use more sophisticated solutions?
Thank You for any reply!
You can pass the reference to the database in the constructor of the handler like this:
handler = new HandlerA(db); //HandlerA needs to deal with database
handler = new HanlderB(); //HandlerB doesn't need to deal with database
HandlerA can look like this:
class HandlerA : public MessageHandler
{
HandlerA(Database& db) { /* ... */ }
int handle(const Request& in, Response& out) { /* ... */ }
};