Mock object is not being returned - unit-testing

There is a Adapter class which calls another legacyService and legacyService calls legacyDao and I want to mock the Legacy service calls.
In the below code SomeBean is returned as null instead of one the one that i created and passed in thenReturn. What could be the issue here?Please help I am new to mocking framework.
public class AdapterImpl implements Adpater{
//Injected through setter or constructor injection
private LegacyService legacy;
public SomeBean myMethod(){
CommonUtils.someStaticMethod()
return legacy.legacyService();
}
}
public class LegacyServiceImpl implements LegacyService{
//Injected through setter or constructor injection
private LegacyDAO ldao;//LegacyDAO is an interface
public SomeBean legacyService(){
return ldao.legacyDAO();
}
}
Test class
#RunWith(PowerMockRunner.class)
#PrepareForTest({CommonUtils.class})
public class AdapterImplTest{
#Mock private LegacyServiceImpl legacyService;
private LegacyDAO legacyDAO;
#Before
public void before(){
MockitoAnnotations.initMocks(this);
}
#Test
public void myMethodTest(){
PowerMockito.mockStatic(CommonUtils.class);
PowerMockito.when(CommonUtils.someStaticMethod()).thenReturn(someString());
legacyDAO = PowerMockito.mock(LegacyDAO.class);
SomeBean bean = new SomeBean(sometring1,somestring2);
PowerMockito.when(legacyDAO.legacyDAO().thenReturn(bean);//I am mocking interface method implementation
legacyService.setLegacyDAO(legacyDAO);
PowerMockito.when(legacyService.legacyService().thenReturn(bean);//same bean as above
AdapterImpl impl = new AdapterImpl();
impl.setLegacyService(legacyService)
//Below method call is not returning the bean that I constructed above it is being returned as null
impl.myMethod();
}
}

The original code posted in the question has many typos like missing parentheses and semi-colons. When I correct them, and fill in some of the methods like AdapterImpl.setLegacyService(), the test passes.
Then, as suggested in my comment, I removed the mocking of LegacyDAO. That mock object should not be needed if LegacyServiceImpl.legacyService() is properly mocked. When I rerun the test, it again passes.
All of which leads me to believe that there is an issue with the injection of the mock LegacyService object into AdapterImpl
FYI here is my passing test code, showing my typo fixes and assumptions about methods not shown in the original question. Hope this helps!
#RunWith(PowerMockRunner.class)
#PrepareForTest({ AdapterImplTest.CommonUtils.class })
public class AdapterImplTest {
#Mock
private LegacyServiceImpl legacyService;
// private LegacyDAO legacyDAO; // removed, no need to mock
#Before
public void before() {
MockitoAnnotations.initMocks(this);
}
#Test
public void myMethodTest() {
PowerMockito.mockStatic(CommonUtils.class);
PowerMockito.when(CommonUtils.someStaticMethod()).thenReturn(someString());
// legacyDAO = PowerMockito.mock(LegacyDAO.class);
SomeBean bean = new SomeBean("sometring1", "somestring2");
// I am mocking interface method implementation
// PowerMockito.when(legacyDAO.legacyDAO()).thenReturn(bean);
// legacyService.setLegacyDAO(legacyDAO);
// same bean as above
PowerMockito.when(legacyService.legacyService()).thenReturn(bean);
AdapterImpl impl = new AdapterImpl();
impl.setLegacyService(legacyService);
// Below method call is not returning the bean that I constructed above
// it is being returned as null
impl.myMethod();
}
private String someString() {
return "hello";
}
public class SomeBean {
public SomeBean(String string, String string2) {
}
}
public interface LegacyService {
public SomeBean legacyService();
}
public interface Adpater {
}
public class AdapterImpl implements Adpater {
// Injected through setter or constructor injection
private LegacyService legacy;
public SomeBean myMethod() {
CommonUtils.someStaticMethod();
return legacy.legacyService();
}
public void setLegacyService(LegacyServiceImpl legacyService) {
legacy = legacyService;
}
}
public class LegacyServiceImpl implements LegacyService {
// Injected through setter or constructor injection
private LegacyDAO ldao;// LegacyDAO is an interface
public SomeBean legacyService() {
return ldao.legacyDAO();
}
public void setLegacyDAO(LegacyDAO legacyDAO) {
ldao = legacyDAO;
}
}
public class LegacyDAO {
public SomeBean legacyDAO() {
return null;
}
}
public static class CommonUtils {
public static String someStaticMethod() {
return "in CommonUtils.someStaticMethod()";
}
}
}

Related

Why is #Inject object(Optional) coming null while running unit test?

I have a class Room, where I inject Optional Person object, this is coming null while running testSuccess. My understanding is it should come non null, since I am setting this to new Person() at the start of the test. Why is it coming null?
public class Room{
#Inject
private Optional<Person> person1
//this is coming null when running test
}
My unit test
public class RoomTest {
#Inject Mocks
private Room testRoom
.....
//Other mocks
private Optional<Person> testPerson
//Not able to mock this since its optional, hence directly setting value in unit test.
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccess() {
testPerson = Optional.of(new Person());
....
}
}
As the name implies, #InjectMocks only injects #Mocks. The testPerson is not a mock. Why not just add an #Inject-ing constructor to the Room class that would accept a person? This way you could just instantiate a testRoom in your test method and your dependency injection will still work.
public class Room{
private Optional<Person> person;
#Inject
public Room(Optional<Person> person) {
this.person = person;
}
}
public class RoomTest {
#Test
public void testSuccess() {
Optional<Person> testPerson = Optional.of(new Person());
Room room = new Room(testPerson);
...
}
}
That said, if you absolutely want to use the annotations and adding the constructor is not an option for you then you can use PowerMock runner to mock the Optional. Conceptually, it can look like the code below. But usually, if you have to use PowerMock there might be something wrong with the code :)
public class Room{
#Inject
private Optional<Person> person;
}
// This is for JUnit4. Using Powermock with JUnit5 will be more involved
#RunWith(PowerMockitoRunner.class)
#PrepareForTest(Optional.class) // to mock the final class
public class RoomTest {
#InjectMocks
private Room testRoom;
#Mock
private Optional<Person> testPerson;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSuccess() {
...
}
}

PowerMock calls real method

I am trying to spy private method with PowerMock but on the line when I define the what should be returned when the private method is called, it calls the method and I am getting and Null Pointer Exception. What PowerMock is calling real method on this line ?
myService= PowerMockito.spy(new MyService(myParam));
.....
PowerMockito.when(myService, "getCLientBy", anyString(), anyString(), anyString()).thenRetur`n(Client.of(setName, new HashSet<>())); // here it calls real method
Ensure that you prepare your class to be used in spy by adding #PrepareForTest(MyService.class)
#RunWith(PowerMockRunner.class)
// We prepare MyService for test because it's final
// or we need to mock private or static methods
#PrepareForTest(MyService.class)
public class YourTestCase {
//...
#Test
public void spyingWithPowerMock() {
MyService classUnderTest = PowerMockito.spy(new MyService(myParam));
//.....
// use PowerMockito to set up your expectation
PowerMockito.doReturn(Client.of(setName, new HashSet<>()))
.when(classUnderTest, "getClientBy", anyString(), anyString(), anyString());
//...
Also make sure provide the correct method name to be invoked.
#user1474111 and #Nkosi
I've built a small simulation of your example.
Maybe you also need to add the Client class in the PrepareForTest annotation.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ MyService.class, Client.class })
public class Example1Test {
#Test
public void testPowerMockito() throws Exception {
MyService myService = PowerMockito.spy(new MyService("myParam"));
PowerMockito.when(myService, "getClientBy", ArgumentMatchers.anyString(), ArgumentMatchers.anyString(),
ArgumentMatchers.anyString()).thenReturn(Client.of("setName", new HashSet<String>()));
myService.run();
Assert.assertEquals("setName", myService.getClient().getName());
}
}
public class MyService {
private Client client;
public MyService(String param) { }
private Client getClientBy(String a, String b, String c) {
return new Client(a + b + c);
}
public Client getClient() {
return this.client;
}
public void setClient(Client client) {
this.client = client;
}
public void run() {
setClient(getClientBy("A", "B", "C"));
}
}
public class Client {
private final String name;
public Client(String name) {
this.name = name;
}
public static Client of(String name, HashSet<String> hashSet) {
return new Client(name);
}
public String getName() {
return name;
}
}

Unit testing callback based on Consumer functional interface

I'm trying to unit test code that runs as callback in a Consumer functional interface.
#Component
class SomeClass {
#Autowired
private SomeInteface toBeMockedDependency;
public method() {
toBeMockedDependency.doSomething(message -> {
// Logic under test goes here
// (implements java.util.function.Consumer interface)
...
});
}
}
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#InjectMocks
private SomeClass someClass;
#Mock
private SomeInteface toBeMockedDependency;
#Test
public void testMethod() {
...
someClass.method();
...
}
}
Essentially I want to provide the tested code some tested "message" via "toBeMockedDependency".
How can the "toBeMockedDependency" be mocked to provide a predefined message?
Is it the right approach?
Don't try to make toBeMockedDependency automatically call your functional interface. Instead, use a #Captor to capture the anonymous functional interface, and then use your test to manually call it.
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#InjectMocks
private SomeClass someClass;
#Mock
private SomeInteface toBeMockedDependency;
#Captor
private ArgumentCaptor<Consumer<Message>> messageConsumerCaptor;
#Test
public void testMethod() {
someClass.method();
verify(toBeMockedDependency).doSomething(messageConsumerCaptor.capture());
Consumer<Message> messageConsumer = messageConsumerCaptor.getValue();
// Now you have your message consumer, so you can test it all you want.
messageConsumer.accept(new Message(...));
assertEquals(...);
}
}

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

#InjectMocks isnt actually injecting mocks

So i have a class that needs to be tested. Lets call it ClassToTest. It has a couple of Dao objects as fields.
Public class ClassToTest {
#Autowired
MyDao dao;
void methodToTest() {
dao.save(something);
}
}
As you can see ClassToTest does not contain any constructor or setter and I am using spring to autowire the fields.
Now, I have a base test class with all the dependencies that classToTest requires:
public abstract BaseTest {
#Mock
MyDao dao;
}
And the testClass extends this BaseTest class :
public class TestClass extends BaseTest {
#InjectMocks
ClassToTest classToTest = new ClassToTest();
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
classToTest.methodToTest();
}
}
This results in a null pointer exception when the save happens. However, if i change setup method to this :
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
classToTest.dao = dao;
}
the test passes.
My understanding was that when a class does not have a constructor or a setter, InjectMocks would inject the mocks by using field injection. Why is that not happening here?
Figured out that this is a bug in the 1.8.5 version that i was using : https://code.google.com/p/mockito/issues/detail?id=229.
Upgrading 1.10 fixed the issue.