Mockito uses method stubbing from other test method in the same class - unit-testing

I am trying to test a method for the happy path and an Exception scenario.
My class looks like this
class MyClass
{
#Autowired
AnotherClass anotherClass;
public Object myMethod() throws MyException
{
try{
//DO SOME STUFF
anotherClass.anotherMethod();
}
catch(Exception e)
{
throw MyException(e);
}
}
}
I am testing the above myMethod like this.
#RunWith(MockitoJUnitRunner.class)
class MyClassTest
{
#Mock
AnotherClass anotherClass;
#InjectMocks
MyClass myClass;
#Test
public void myMethodTest()
{
when(anotherClass.anotherMethod()).thenReturn("Mocked data");
myClass.myMethod();
}
#Test(expected=MyException.class)
public void myMethodExpTest()
{
when(anotherClass.anotherMethod()).thenThrow(MyException.class);
myClass.myMethod();
}
}
When I checked the code coverage using Jacoco, it does not coverage the exception catch block. I tried debugging the test in my Eclipse IDE. I am getting the "Mocked Data" for the exception test method. It appears to be the mocking to that method is not getting reset for the second method.
Is there a way to flush the method mocking/stubbing from previous test methods?

First I would consider this a bug. But you can manually reset mocks
#Before
public void resetMock() {
Mockito.reset(anotherClass);
}

Related

Mockito- thenReturn(true) still returns false on a mock object

I recently started reading up about Mockito. The following line of code must return true as per my understanding, but it returns false.
Test Class
public class PersonServiceImplTest {
Car car;
#InjectMocks
CarServiceImpl carService;
#Mock
CarDAOImpl carDAO;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testUpdateCar() {
int carId = 1;
Mockito.when(carDAO.getCarById(any(Integer.class))).thenReturn(new Car());
carService.updateCar(carId);
Mockito.when(carDAO.isLicenseExpired(any(Car.class))).thenReturn(true);
Mockito.verify(carDAO).updateCar(any(Car.class));
Mockito.verify(carDAO, times(1)).isLicenseExpired(any(Car.class));
Mockito.verify(carDAO, times(1)).issueLicense(any(Car.class));
}
}
Class to be tested
public class CarServiceImpl implements CarService {
#Autowired carDAO carDAO;
#Override
public Response updateCar(int carId) {
Car car =carDAO.getCarById(carId);
try {
carDAO.updateCar(car);
if(carDAO.isLicenseExpired(car)))
carDAO.issueLicense(car);
} catch (Exception e) {
log.error(e.getMessage());
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
return Response.ok(Status.CREATED).build();
}
CarDAOImpl deals with the database, if needed, will update that too.
Thanks in advance.
These two lines are ordered incorrectly:
carService.updateCar(carId);
Mockito.when(carDAO.isLicenseExpired(Mockito.any(Car.class))).thenReturn(true);
The first line in that pair invokes the class-under-test and the second line sets up an expectation of how your carDAO should behave inside the class-under-test. So, you are setting the expectation after you invoke the class-under-test.
The following test will pass:
#Test
public void testUpdateCar() {
int carId = 1;
// establish expectations of how carDAO should behave inside updateCar()
Mockito.when(carDAO.getCarById(Mockito.any(Integer.class))).thenReturn(new Car());
Mockito.when(carDAO.isLicenseExpired(Mockito.any(Car.class))).thenReturn(true);
// invoke the class-under-test
carService.updateCar(carId);
// verify that CarService used CarDAO correctly
Mockito.verify(carDAO).updateCar(Mockito.any(Car.class));
Mockito.verify(carDAO).isLicenseExpired(Mockito.any(Car.class));
Mockito.verify(carDAO).issueLicense(Mockito.any(Car.class));
}

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.

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.

PowerMockito fails intermittently to mock final void method for an abstract class

I am using TestNG 6.8.8, Mockito 1.9.5 and PowerMock 1.5.4. When I mock a final void method, the test passes sometimes and fails sometimes with error UnfinishedStubbingException.
Is this a PowerMock bug?
public abstract class Parent implements Serializable {
protected abstract void validate();
public final void validateSomething() {
// some code here
}
}
#PrepareForTest({ Parent.class })
public class ParentTest {
#Test
public final void testSomeMethod() {
Parent parentObj = PowerMockito.mock(Parent.class);
doNothing().when(parentObj).validateSomething();
TestCodeThatResultsInCallToParentObj.validateSomething();
}
}
Error message:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:36)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
You can use delegation and wrap the execution of that class in your class.
class ParentWrapper {
private final Parent delegate;
ParentWrapper(Parent delegate) {
this.delegate = delegate;
}
void validateSth() {
delegate.validateSth();
}
}
and now you can mock the ParentWrapper without any Powermock.