Mockito Test Failure - Actually, there were zero interactions with this mock - unit-testing

Is there any other way to write test case for below case, needs to write test case for runStudentService method . Tried to write test case as below but its throwing : "wanted but not invoked - Actually, there were zero interactions with this mock."
#Component
public class StudentScheduler {
#Autowired
private StudentService studentService;
#Scheduled(cron = "${cron.students}")
public void runStudentService() {
try {
studentService.startStudetsTest();
} catch (Exception e) {
LOG.error("Error occured during test" + e);
throw(e);
}
}
}
#RunWith(SpringJUnit4ClassRunner.class)
public class StudentSchedulerTest {
#Mock
private StudentService studentService;
StudentScheduler scheduler = Mockito.mock(StudentScheduler.class);
#Test
public void jobRuns() {
Mockito.doNothing().when(scheduler).runStudentService();
verify(scheduler, Mockito.times(1)).runStudentService();
}
}

Your mocked StudentScheduler class is not using your mocked studentService instance. Double check the instance studentService instance inside the runStudentService() function is the same instance as your mock studentService.
Pass that mocked studentService instance into the runStudentService() function to be invoked!

Related

handling exception for RestAPI unit test

I have a method
public class ActivityManager {
private ActivityManager activityManager_;
#Autowired
public ActivityManager(ActivityManager activityManage)
{
activityManager_= activityManage;
}
#RequestMapping(value ="activityManager/", method = RequestMethod.GET)
public List<Data> getData() throws RestControllerException {
try {
return activityManage_.fetchData();
} catch (Exception ex) {
throw new RestControllerException();
}
}
}
And I tried to test the throw exception but it does not work. I got confused into the case what's the status() for resultmatcher should be.
#Test(expected = RestControllerException.class)
public void getDataError() throws Exception {
ActivityManager activityManagerMock = Mockito.mock(ActivityManager
.class);
doThrow(RestControllerException.class).when(activityManagerMock).fetchData();
mockMvc_.perform(get("/activityManager")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isInternalServerError());
}
Is there any document that I can read more about handling exception for restapi unit test?
Thanks
#Autowired
private ActivityManagerService activityManager;
This will inject the actual bean into the controller not the mock which you created.
Add this inside your test class.
#Autowired
private ControllerBean controller;
#Before
public void init(){
ReflectionTestUtils.setField(controller, "activityManager", activityManagerMock);
}
This will set the MockObject into activityManager of Controller.
And hence while running test the mock objects fetchData() will be called which inturn throws the exception.

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

Mockito Mock log4j appender is not invoked while running unit test

I am trying to unit test the log statements generated in my code. I am using slfj, log4j and Mockito. I am using the similar code as below from the blog at
http://bloodredsun.com/2010/12/09/checking-logging-in-unit-tests/
When I run the test it throws exception saying that there are 0 invocations at line:
verify(mockAppender).doAppend(captorLoggingEvent.capture());
Error Message:
Wanted but not invoked: mockAppender.doAppend();
-> at testClass.testLogAdviceAfterReturning(DpsOpsLoggerTest2.java:94) Actually, there were zero interactions with this mock.
I see the logs printed on the console though. Request you to kindly help.
#RunWith(MockitoJUnitRunner.class)
public class ExampleThatLogsTest {
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor captorLoggingEvent;
#Before
public void setup() {
LogManager.getRootLogger().addAppender(mockAppender);
}
#After
public void teardown() {
LogManager.getRootLogger().removeAppender(mockAppender);
}
#Test
public void shouldConcatAndLog() {
//given
ExampleThatLogs example = new ExampleThatLogs();
//when
String result = example.concat("foo", "bar");
//then
assertEquals("foobar", result);
verify(mockAppender).doAppend(captorLoggingEvent.capture());
LoggingEvent loggingEvent = captorLoggingEvent.getValue();
//Check log level
assertThat(loggingEvent.getLevel(), is(Level.INFO));
//Check the message being logged
assertThat(loggingEvent.getRenderedMessage(),
is("String a:foo, String b:bar"));
}
}
I tried to emulate your case ,At my end it is working fine
//Log Util
public class LogUtil{
final static Logger logger = Logger.getLogger(LogUtil.class);
public static Log`enter code here`ger getLogger()
{
return logger;
}
//class
public class RunMe {
public String runMe(String parameter) {
LogUtil.getLogger().info("This is info : " + parameter);
return "In runner " + parameter;
}
}
// Unit Test
#RunWith(MockitoJUnitRunner.class)
public class LoggerTest {
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor captorLoggingEvent;
#Before
public void setup() {
LogUtil.getLogger().addAppender(mockAppender);
}
#Test
public void shouldConcatAndLog() {
RunMe runner=new RunMe();
String result=runner.runMe("XYZ");
assertEquals("In runner XYZ",result);
verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture());
LoggingEvent logevent= (LoggingEvent) captorLoggingEvent.getValue();
assertThat(logevent.getLevel(), is(Level.INFO));
}
#After
public void tearDown() {
LogUtil.getLogger().removeAllAppenders();
}
}
I know this is a little bit outdated, but I was struggling with this too. I was logging statements at DEBUG level in the class under test. My configuration in logback.xml for the class under test was set to INFO. Changing my logging statement to INFO allowed the test to pass. In addition, I also read this Github post that is really concise and a clean implementation of testing log output. Hope others will find it useful.

How to mock web service call without passing mocked class as parameter

I have a web serivce class which need to unit tested.
Here is class which is under test
public class ValidatePaymentMessage {
public CsmValidationResultX validatePaymentmsg(String csmName, String base64PayloadXML){
//Call Web Service to validate Payment
CsmValidationResultX responseMsg=null;
PaymentManagerWebService paymentManagerWebService = new PaymentManagerWebService();
PaymentManagerWebServiceImpl serviceAddrs = paymentManagerWebService.getPaymentManagerWebServicePort();
try {
responseMsg = serviceAddrs.validatePayment(csmName, base64PayloadXML);
} catch (MPMWebServiceException e) {
e.printStackTrace();
}
return responseMsg;
}
}
Here is my Junit class
public class ValidatePaymentMessageTest {
#Test
public void testValidatePaymentmsg() throws MPMWebServiceException {
CsmValidationResultX csmResult= EasyMock.createMock(CsmValidationResultX.class);
PaymentManagerWebServiceImpl paymentManagerImpl = EasyMock.createMock(PaymentManagerWebServiceImpl.class);
EasyMock.expect(paymentManagerImpl.validatePayment("SEPA","BASE64XML")).andReturn(csmResult).anyTimes();
PaymentManagerWebService paymentManager = EasyMock.createMock(PaymentManagerWebService.class);
EasyMock.expect(paymentManager.getPaymentManagerWebServicePort()).andReturn(paymentManagerImpl).anyTimes();
ValidatePaymentMessage validatePayment=new ValidatePaymentMessage();
CsmValidationResultX response = validatePayment.validatePaymentmsg("SEPA", "base64PayloadXML");
System.out.println(response.getCsmValidationResult().isValid());
}
}
When I run this Junit it is calling actual web service instead of mocked one's.So Please let me know how can i resolve this problem.
You are still instantiating a real PaymentManagerWebService in validatePaymentmsg(), so the mocks do not help. You can't mock construction of local variables with EasyMock, but you can with PowerMock. So if changing the code to receive and instance of PaymentManagerWebService is not an option, mock its construction with PowerMock.
#RunWith(PowerMockRunner.class)
#PrepareForTest(ValidatePaymentMessage.class)
public class ValidatePaymentMessageTest {
#Test
public void testValidatePaymentmsg() throws MPMWebServiceException {
// .....
PowerMock.expectNew(PaymentManagerWebService.class).andReturn(paymentManager);
//....
}
}