Cast a mocked object using google mock - unit-testing

I'm using google mock framework to perform some unit tests over my code. I have a class named SerialPortManager with the constructor:
SerialPortManager(SerialPortFactoryInterface* serialPortFactory,SerialParserInterface* serialParsers[PORT_COUNT]);
To perform the tests I have the following test fixture
class SerialPortManagerTest: public testing::Test {
protected:
SerialPortManager* manager;
MockSerialPortFactory *portFactory;
SerialParserInterface *parsers[PORT_COUNT];
virtual void SetUp() {
portFactory = new MockSerialPortFactory();
for (int i = 0; i < PORT_COUNT; i++) {
parsers[i] = new MockSerialParser();
}
manager = 0;
}
Now, on one of my tests I need to set an expectation on one of the mocked SerialParsers. I try to do it as
EXPECT_CALL(*parsers[0], GetPendingCommands()).Times(1);
But I get
Method 'gmock_GetPendingCommands' could not be resolved
¿Is there a way to cast the SerialParserInterface pointer to the mocked type?

Solved by casting the argument of the constructor. I declare the parser array as MockSerialParser *parsers[PORT_COUNT], I instantiate the array objects as MockSerialParser * and then I pass the array to the constructor as manager = new SerialPortManager(portFactory,(SerialParserInterface**)parsers);

Related

Using spy to mock a full object created in the class which is tested

I have the following structure:
class A {
public A(String p){
// ...
}
public String AMethod(String p){
// ...
}
}
class B {
int method(String param){
A a = new A(param); int n;
String s = A.AMethod(param);
// ... (initializes n, ...)
return n;
}
}
Now I want to test method in class B but control the output of AMethod when it is called. But since I do not create the object A in the test class of B, I cannot mock it normally - how can I mock object A instead?
I tried Mockito.spy but it doesn't seem to work:
this.ASpy = spy(new A());
when(ASpy.createSession(any())).then(invocation -> {
// ... (*)
});
(*) still doen't get called... but spy should be the right solution, shouldn't it? My problem is: I never create an object A in my test class, only in method such an object is created but not in the test class.
The best way to handle this (if possible) would be to modify the code of class B so that object A was injected into the method (passed as a parameter, set as a class field or instantiated with usage of a factory class - the factory would be injected as a field and the factory object could be mocked in the test to return a mocked object A).
If actual code modifications are not possible, you could use PowerMock's whenNew method and return a mocked object in your test.
A side note: if you're using JUnit 5, PowerMock may not be a viable solution - read more here.

gmock Multiple mock instances, but only one is effective

I would like to test a class (Controller) that manages a set of entities of a certain kind. Entities are created internally in this class because a factory would be an overkill here, so here is how I inject mocks into it:
class TestController : public Controller {
public:
/* Mechanism for a mock injection */
std::shared_ptr<IEntity> create_entity() override {
return temp_entity;
}
/* Variable to hold the entity being injected */
std::shared_ptr<IEntity> temp_entity;
};
Production code invokes create_entity() in the Controller class, which I overload here, and adds the result to a container. temp_entity is the way I supply my mocks and the test, where I supply two distinct mock instances, looks like this:
class MockEntity : public IEntity {
MOCK_METHOD0(perform_operation, bool());
}
TEST(ControllerTest, TestFailure) {
std::shared_ptr<TestController> controller = std::make_shared<TestController>();
std::shared_ptr<MockEntity> entity1 = std::make_shared<MockEntity>();
controller->temp_entity = entity1;
controller->add_entity(); // This invokation fetches the result of create_entity()
std::shared_ptr<MockEntity> entity2 = std::make_shared<MockEntity>();
controller->temp_entity = entity2;
controller->add_entity(); // This invokation fetches the result of create_entity()
EXPECT_CALL(*entity1, perform_operation().WillOnce(::testing::Return(true));
EXPECT_CALL(*entity2, perform_operation().WillOnce(::testing::Return(false));
controller->run();
}
controller.run() only concurrently executes perform_operation() on each of the entities.
When the test is run, the function in the second expectation is called twice and the function in the first expectation is not run at all. I am sure that the controller operates on two distinct versions of an entity before executing run() function.
Is there a fundamental problem in what I am trying to do? How can I separate my expectations for these two mocks in a test? I tried creating two distinct mock classes with perform_operation() method being implemented in the mock body and when running the test in the debugger I still hit the method of one mock class twice.
The test looks correct and the way, how you inject the mocks into the system under test, is an absolutely reasonable method.
I suppose, the critical issue is in your class under Test. I rebuild your Test with the following controller:
class Controller {
public:
virtual std::shared_ptr<IEntity> create_entity() = 0;
void add_entity() {
auto entity = create_entity();
entities.push_back(entity);
}
void run() {
for(auto e : entities) {
bool i = e->perform_operation();
}
}
std::vector<std::shared_ptr<IEntity> > entities;
};
With this class the test succeeded like expected.

How to verify some other object was constructed, when using mockito

I have following Java code that I want to test. What I am having difficulty is figuring out how do I verify that call to handleAppVersionRequest , actually constructs AppVersionResponse object. Is there any way to do that using Mockito?
Here code is code for method:
class MyClass {
public void handleAppVersionRequest(String dataStr,
final int dataChannelId) {
String ver = "1.0";
final AppVersionResponse resp = new AppVersionResponse(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, getGson().toJson(resp));
}
}
And here is method for test:
#Test
public void testHandleAppVersionRequest() throws Exception {
MyClass presenter = Mockito.spy(new MyClass());
String versionRequestJson = "{\"command\":1}";
when(presenter.getGson()).thenReturn(gSon);
presenter.handleAppVersionRequest(versionRequestJson,0);
// How do I verify that AppResponse object was constructed?
verify(presenter,times(1)).sendResponse(anyInt(),anyString());
}
If you must test the creation of the object during a unit test, you can extract a factory, mock it for your test, and then verify that the create method is called on it.
At the same time, consider spending some time looking at some tutorials for Mockito and unit testing in general, like this one. You should choose one class that is going to be the 'system under test'. Don't spy or mock this class! Instead, pass in mocks as dependencies that you will use to test the behaviour of your class.
Here is a factory extracted from your MyClass:
class AppVersionResponseFactory {
AppVersionResponse create(String version) {
return new AppVersionResponse(version);
}
}
Then the refactored version of your class where the dependencies (Gson and the factory) are passed in through the constructor:
class MyClass {
//dependencies that can now be mocked!
private final AppVersionResponseFactory appVersionResponseFactory;
private final Gson gson;
//pass the mockable dependencies in the constructor of the system under test!
public MyClass(AppVersionResponseFactory appVersionResponseFactory, Gson gson) {
this.appVersionResposeFactory = factory;
this.gson = gson;
}
public void handleAppVersionRequest(String dataStr, final int dataChannelId) {
String ver = "1.0";
AppVersionResponse resp = AppVersionResponseFactory.create(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, gson.toJson(resp));
}
}
Now your test looks something like this:
//mocks
AppVersionResponseFactory mockAppVersionResposeFactory;
Gson mockGson;
//system under test
MyClass myClass;
#Before
public void setUp() {
mockAppVersionResposeFactory = Mockito.mock(AppVersionResponseFactory.class);
mockGson = Mockito.mock(Gson.class);
myClass = new MyClass(mockGson, mockAppVersionResposeFactory);
}
#Test
public void testHandleAppVersionRequest() throws Exception {
String versionRequestJson = "{\"command\":1}";
myClass.handleAppVersionRequest(versionRequestJson, 0);
verify(appVersionResposeFactory).create("1.0");
}
Please note that although your question asks for a way to verify the construction of an object, a better test would probably test the final outcome of that method i.e., that sendResponse was called with the correct dataChannelId and correct JSON. You can use the same techniques in this answer to do that i.e., extracting a dependency (perhaps a ResponseSender?), passing it in the constructor for your MyClass, mocking it in the test, then calling verify on it.

Unable to get mocked instance of Executor in separate class

I am trying to mock ExecutorService and Executors from java.util.concurrent package.
I am able to get the mocked object if I try to get the object within the same class (test class) where I am mocking the object. However if I try to get the mocked object in a different class (the class I want to test) then it returns actual object from java.util.concurrent. Following is the code snippet.
The class I want to test:
public class MyClass
{
public void myMethod()
{
ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());
for (int count = 0; count < 2; count++)
{
executorService.submit(new Thread());
}
}
}
class MyThreadFactory implements ThreadFactory
{
#Override
public Thread newThread(Runnable r)
{
return null;
}
}
My Test class looks like:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Executors.class)
public class MyClassTest
{
#Test
public void testMyMethod()
{
prepareMocks();
//Code to get mocked object (See testMethod below)
}
private void prepareMocks()
{
ExecutorService executorService = PowerMock.createMock(ExecutorService.class);
EasyMock.expect(executorService.submit(EasyMock.anyObject(Runnable.class))).andReturn(null).anyTimes();
PowerMock.mockStatic(Executors.class);
EasyMock.expect(Executors.newFixedThreadPool(EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))).andReturn(executorService).anyTimes();
PowerMock.replay(executorService, Executors.class);
}
}
If MyClassTest.testMyMethod() is as below, it returns mocked oject.
#Test
public void testMyMethod()
{
prepareMocks();
//Following code reurned mocked instance of ExecutorService
ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());
for (int count = 0; count < 2; count++)
{
executorService.submit(new Thread());
}
}
However if I change the test method to call myClass.myMethod() it returns actual instance instead of mocked instance in myMethod().
#Test
public void testMyMethod()
{
prepareMocks();
/*
* Within myClass.myMethod(), Executors.newFixedThreadPool() returns actual instance of ThreadPoolExecutor
* instead of mocked object
*/
MyClass myClass = new MyClass();
myClass.myMethod();
}
I am expecting to get a mocked instance of Executors/ExecutorService in myClass.myMethod.
Is this the expected behavior? Could anyone explain the behavior? Am I missing anything?
You need to let the class know that there is going to be a Mock incoming. In your #PrepareForTest(), try also including the class that is calling the static. This way you are telling it to mock the execution of the static, as well as telling it where this mock is going to be taking place. Try updating the #PrepareForTest({Executors.class, MyClass.class}).
When you have it so your test class is calling the static directly, you have the Executors.class in the #PrepareForTest() so it will know to "inject" that mock into the execution. When you call your other class, at runtime the class you are calling it doesn't know to use the mock version of your static class, which is why it is resorting to the original code that it knows about, not the mock outside its scope. Adding the class that CALLS the static object (the one you test), will allow the static mock you have to be hooked in when it is ran.

Mocking a method using Mockito

Does mocking a method using mockito ensures that mocked method will never be called? I have Main class which contains some code i want to write unit tests for and i have one unit test class MainTest which contains unit tests for Main class.
eg:
Source Class:
package abc;
public class Main {
public int check1() {
int num = 10;
num = modify(num);
return num;
}
public int modify(int num) {
if (num % 10 == 0) return num / 10;
return -1;
}
}
Junit Test (using mockito)
package abc;
import junit.framework.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
public class MainTest {
private static Main main;
#BeforeClass
public static void setUp() {
main = Mockito.mock(Main.class);
Mockito.when(main.modify(10)).thenReturn(5);
}
#Test
public void testCheck1() {
Test1 main1 = new Main();
int num = main.check1();
Assert.assertEquals(5, num);
}
}
This test is failing. Why?
EDITED
Because you didn't provide a behavior for check1(). ALL methods get mocked, so without you providing a behavior, check1() returns a default value for the return type of int, which is 0. Furthermore, check1() since it is mocked does not even get to call modify().
If you are trying to test a class, you never mock the Class Under Test. On rare occasion, you might have to Spy a class under test. Rather, you mock collaborators only.
I am guessing your example was a contrived one (I hope). But if you are writing and testing a class where you think you want to modify some internal method's behavior, I see two likely probabilities:
You may need to refactor the functionality of the method you want to mock-out into a collaborator class. Then it makes sense to go ahead and mock that behavior as a collaborator.
You may also may need to modify the API so that you can pass in what is going to change. In your case, check1() hard-codes the value it passes to modify(), which is why you are trying to mock modify(). If instead that value were a parameter to check1() or a settable field in class Main, then there wouldn't even be a need to use a mock at all.
The Problem with your Test is, that you do not use your newly created main1 object.
If you want to change the behaviour of your systen under test (SUT) you would normally do something like this:
#Test
public void testCheck1() {
Test1 main1 = new Main(){
public int modify(int num) {
return 5; // hard coded return value
}
};
int num = main1.check1();
Assert.assertEquals(5, num);
}
This creates a subclass of Main with a new implementation of the modify-method.
This is an important technique for replacing hard-to-test methods in your SUT. You would normally use it to avoid expensive remote calls or similar.
It is of course possible to use a Mockito spy like this:
#Test
public void testCheck1() {
Test1 main1 = spy(new Main());
stub(main1.modify(10)).toReturn(5);
int num = main1.check1();
Assert.assertEquals(5, num);
}
Though i am late,it might be useful to some one. Just to add to #VivaceVivo answer: when using spies please consider doReturn|Answer|Throw() family of methods for stubbing. Sometimes it's impossible or impractical to use when(Object) for stubbing spies. more info here