Unit testing that log message written when exception caught - java

Here is the code that I am working with. In this test I want to verify that the log method is being called when an exception is caught.
public class SuperClass(){
public void log()
{
do some logging;
}
}
public class ClassUnderTest extends SuperClass(){
public String methodbeingtested(Object param)
{
try
{
String a = SomeObject.
methodthatthrowsexception(param);//static method, throws JAXB/NPE
}
catch(Exception exp)
{
log("log msg",exp);//inherited method
}
}
}
public class ClassUnderTestTest {
#Test
public testmethodbeingtested(){
ClassUnderTest cut = new ClassUnderTest()
ClassUnderTest cutspy = Mockito.spy(cut);
cutspy.methodbeingtested(param);
Mockito.verify(cutspy).log("log msg", new Exception()); // exp is needed to here.
}
}
After looking at several samples, the above was the closest I could get. This testcase forces an exception. But it fails to verify the log method call as Mockito.verify requires the exact exception (exp) that is caught, which the test case does not have access to.
Is there any other way to test this scenario?

Mockito's verify method can be used with argument matchers. If you want to verify that log was called, with any Exception at all as the second argument, you can just write
verify(cutspy).log(eq("log msg"), any(Exception.class));
I've assumed that you have the right static imports for verify, eq and any.
As an aside, this test does not need PowerMock. Your line PowerMock.expectLastCall().once(); is both redundant and confusing, and should probably be removed, along with the #PrepareForTest annotation.

Instead of spying on ClassUnderTest, you should mock the logging framework, inject it into the class and then verify that the log method gets called. Id' also mock the SomeObject class and have it throw exception.
As an aside, you should really evaluate if you need to verify your log statements. Perhaps you have a valid reason to do so but typically, asserting/verifying to this extent is not required and will only make your tests brittle.

Related

Sometimes we get error: "Previous MockitoSession was not concluded with 'finishMocking()'" [duplicate]

I am getting following exception while running the tests. I am using Mockito for mocking. The hints mentioned by Mockito library are not helping.
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.a.b.DomainTestFactory.myTest(DomainTestFactory.java:355)
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 a.b.DomainTestFactory.myTest(DomainTestFactory.java:276)
..........
Test Code from DomainTestFactory. When I run the following test, I see the exception.
#Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); // Line 355
}
private List<SomeModel> getSomeList() {
SomeModel model = Mockito.mock(SomeModel.class);
Mockito.when(model.getName()).thenReturn("SomeName"); // Line 276
Mockito.when(model.getAddress()).thenReturn("Address");
return Arrays.asList(model);
}
public class SomeModel extends SomeInputModel{
protected String address;
protected List<SomeClass> properties;
public SomeModel() {
this.Properties = new java.util.ArrayList<SomeClass>();
}
public String getAddress() {
return this.address;
}
}
public class SomeInputModel{
public NetworkInputModel() {
this.Properties = new java.util.ArrayList<SomeClass>();
}
protected String Name;
protected List<SomeClass> properties;
public String getName() {
return this.Name;
}
public void setName(String value) {
this.Name = value;
}
}
You're nesting mocking inside of mocking. You're calling getSomeList(), which does some mocking, before you've finished the mocking for MyMainModel. Mockito doesn't like it when you do this.
Replace
#Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
Mockito.when(mainModel.getList()).thenReturn(getSomeList()); --> Line 355
}
with
#Test
public myTest(){
MyMainModel mainModel = Mockito.mock(MyMainModel.class);
List<SomeModel> someModelList = getSomeList();
Mockito.when(mainModel.getList()).thenReturn(someModelList);
}
To understand why this causes a problem, you need to know a little about how Mockito works, and also be aware in what order expressions and statements are evaluated in Java.
Mockito can't read your source code, so in order to figure out what you are asking it to do, it relies a lot on static state. When you call a method on a mock object, Mockito records the details of the call in an internal list of invocations. The when method reads the last of these invocations off the list and records this invocation in the OngoingStubbing object it returns.
The line
Mockito.when(mainModel.getList()).thenReturn(someModelList);
causes the following interactions with Mockito:
Mock method mainModel.getList() is called,
Static method when is called,
Method thenReturn is called on the OngoingStubbing object returned by the when method.
The thenReturn method can then instruct the mock it received via the OngoingStubbing method to handle any suitable call to the getList method to return someModelList.
In fact, as Mockito can't see your code, you can also write your mocking as follows:
mainModel.getList();
Mockito.when((List<SomeModel>)null).thenReturn(someModelList);
This style is somewhat less clear to read, especially since in this case the null has to be casted, but it generates the same sequence of interactions with Mockito and will achieve the same result as the line above.
However, the line
Mockito.when(mainModel.getList()).thenReturn(getSomeList());
causes the following interactions with Mockito:
Mock method mainModel.getList() is called,
Static method when is called,
A new mock of SomeModel is created (inside getSomeList()),
Mock method model.getName() is called,
At this point Mockito gets confused. It thought you were mocking mainModel.getList(), but now you're telling it you want to mock the model.getName() method. To Mockito, it looks like you're doing the following:
when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);
This looks silly to Mockito as it can't be sure what you're doing with mainModel.getList().
Note that we did not get to the thenReturn method call, as the JVM needs to evaluate the parameters to this method before it can call the method. In this case, this means calling the getSomeList() method.
Generally it is a bad design decision to rely on static state, as Mockito does, because it can lead to cases where the Principle of Least Astonishment is violated. However, Mockito's design does make for clear and expressive mocking, even if it leads to astonishment sometimes.
Finally, recent versions of Mockito add an extra line to the error message above. This extra line indicates you may be in the same situation as this question:
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
For those who use com.nhaarman.mockitokotlin2.mock {}
Workaround 1
This error occurs when, for example, we create a mock inside another mock
mock {
on { x() } doReturn mock {
on { y() } doReturn z()
}
}
The solution to this is to create the child mock in a variable and use the variable in the scope of the parent mock to prevent the mock creation from being explicitly nested.
val liveDataMock = mock {
on { y() } doReturn z()
}
mock {
on { x() } doReturn liveDataMock
}
Workaround 2
Make sure all your mocks that should have a thenReturn.
GL
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
E.g. thenReturn() may be missing.
For mocking of void methods try out below:
//Kotlin Syntax
Mockito.`when`(voidMethodCall())
.then {
Unit //Do Nothing
}
AbcService abcService = mock(AbcService.class);
Check the syntax:
doThrow(new RunTimeException()).when(abcService).add(any(), any())
Common Mistake as seen below:
A. doThrow(new RunTimeException()).when(abcService.add(any(), any()))
Similarly, check for when().thenReturn(), so on.
I am so exited with detailed answer of #Luke Woodward that want to share a workaround.
As #Luke Woodward explained, we can not have two calls like
when(mainModel.getList());
// ...
when(model.getName()).thenReturn(...);
Than can occurs in call chain.
But in case you will use construction:
doReturn(mockToken("token3")).when(mock).getAccessToken();
when
OAuth2AccessToken mockToken(String tokenVal){
OAuth2AccessToken token = Mockito.mock(OAuth2AccessToken.class);
doReturn( 60 ).when(token).getExpiresIn();
doReturn(tokenVal).when(token).getValue();
return token;
}
all will works as expected.

Can't mock java.lang.System#exit(int) method with PowerMock

My application has a flow that in the end of it the method System.exit(int) is being called.
I'm trying to test this flow by running a test using TestNG.
However, when running the test I'm getting this weird message although the test was completed:
Just for finding the root cause, I removed the System.exit(int) from the real flow and the test passed as expected, so the problem here is the System.exit(int) method.
In order to solve this issue I've tried to mock the problematic method but couldn't find the right way to do it. Here is what I did
I added java.lang.System.class under #PrepareForTest in the tests class.
added PowerMockito.mockStatic(java.lang.System.class) in the test
I've tried to mock the method in two ways:
a.
PowerMockito.replace(PowerMockito.method(System.class, "exit", int.class))
.with((proxy, method, args) -> null);
When running this way looks like the mock is not working, because I'm getting the same message at the end of the test which I also got when not applying any mocks on System.exit(int)
b.
PowerMockito.doNothing().when(System.class, "exit", Mockito.any());
In this way I'm getting this exception at the beginning of the test:
org.powermock.reflect.exceptions.MethodNotFoundException: No method found with name 'exit' with parameter types: [ <none> ] in class java.lang.System.
I already mocked some methods in this ways, not sure why with System.exit(int) it is not working.
Any ideas?
Thanks
Interesting question, I didn't know either, but apparently this is possible without the use of Powermock, through the use of SecurityManagers. Quoting from the original post:
Today I was writing test for one of our command line tools, and I had
this problem where the method dumping everything, which I really
needed to be called since that’s the outcome I was checking, also
called System.exit(). I had to find a way to test this anyway. I
thought about using PowerMock and mocking system but that would have
been complicated because I would have to find the exact class calling
the System.exit(). So here is another solution to avoid the
System.exit to exit (yes that’s possible I didn’t know about that
either).
The secrets lays in the SecurityManager mechanism of Java, this class
not only allows you to check permissions, but also to check exit
event. Therefore you can throw an exception if you want to stop the
exit
Below is a full sample I tested in IJ. Please note the sample is supposed to fail on purpose with:
java.lang.AssertionError:
Expected: is <10>
but: was <5>
Expected :is <10>
Actual :<5>
package com.example;
import org.junit.Test;
import java.security.Permission;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class SystemExitTest {
#Test
public void shouldExitWithSpecificCode() {
//save the initial security manager (probably null)
SecurityManager initialSecurityManger = System.getSecurityManager();
try {
// set security manager
System.setSecurityManager(new NoExitSecurityManager());
// execute code under test
new MyClass().exit(5);
// ensure this point is not reached by any chance
fail("Should've thrown ExitException");
} catch (ExitException e) {
// validate exit code
assertThat(e.status, is(10)); // <== this fails on purpose
} finally {
// restore initial security manager (otherwise a new ExitException will be thrown when the JVM will actually exit)
System.setSecurityManager(initialSecurityManger);
}
}
// class under test
public static class MyClass {
public void exit(int code) {
System.exit(code);
}
}
// exception to be thrown by security manager when System.exit is called
public static class ExitException extends SecurityException {
public final int status;
public ExitException(int status) {
this.status = status;
}
}
// custom security manager
public static class NoExitSecurityManager extends SecurityManager {
#Override
public void checkPermission(Permission perm) {
}
#Override
public void checkPermission(Permission perm, Object context) {
}
#Override
public void checkExit(int status) {
super.checkExit(status);
throw new ExitException(status);
}
}
}

Unit Testing Java Code - Mocking a non-static method of a different class

public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}

How to verify static void method has been called with power mockito

I am using the following.
Powermock-mockito 1.5.12
Mockito 1.95
junit 4.11
Here is my utils class
public void InternalUtils {
public static void sendEmail(String from, String[] to, String msg, String body) {
}
}
here is gist of the class under test:
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail(...);
}
}
}
And here is the test:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalService {
public void verifyEmailSend() {
mockStatic(Internalutils.class);
doNothing().when(InternalUtils, "sendEmail", anyString(), any(String.class), anyString(), anyString());
Order order = mock(Order.class);
when(order.isSuccessful()).thenReturn(true);
InternalService is = new InternalService();
verifyStatic(times(1));
is.processOrder(order);
}
}
The above test fails. The verification mode given is none, but according to the code, if order is successful than email must be send.
If you are mocking the behavior (with something like doNothing()) there should really be no need to call to verify*(). That said, here's my stab at re-writing your test method:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest { //Note the renaming of the test class.
public void testProcessOrder() {
//Variables
InternalService is = new InternalService();
Order order = mock(Order.class);
//Mock Behavior
when(order.isSuccessful()).thenReturn(true);
mockStatic(Internalutils.class);
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
//Execute
is.processOrder(order);
//Verify
verifyStatic(InternalUtils.class); //Similar to how you mock static methods
//this is how you verify them.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
}
}
I grouped into four sections to better highlight what is going on:
1. Variables
I choose to declare any instance variables / method arguments / mock collaborators here. If it is something used in multiple tests, consider making it an instance variable of the test class.
2. Mock Behavior
This is where you define the behavior of all of your mocks. You're setting up return values and expectations here, prior to executing the code under test. Generally speaking, if you set the mock behavior here you wouldn't need to verify the behavior later.
3. Execute
Nothing fancy here; this just kicks off the code being tested. I like to give it its own section to call attention to it.
4. Verify
This is when you call any method starting with verify or assert. After the test is over, you check that the things you wanted to have happen actually did happen. That is the biggest mistake I see with your test method; you attempted to verify the method call before it was ever given a chance to run. Second to that is you never specified which static method you wanted to verify.
Additional Notes
This is mostly personal preference on my part. There is a certain order you need to do things in but within each grouping there is a little wiggle room. This helps me quickly separate out what is happening where.
I also highly recommend going through the examples at the following sites as they are very robust and can help with the majority of the cases you'll need:
https://github.com/powermock/powermock/wiki/Mockito (PowerMock Overview / Examples)
http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html (Mockito Overview / Examples)
Thou the above answer is widely accepted and well documented, I found some of the reason to post my answer here :-
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
Here, I dont understand why we are calling InternalUtils.sendEmail ourself.
I will explain in my code why we don't need to do that.
mockStatic(Internalutils.class);
So, we have mocked the class which is fine.
Now, lets have a look how we need to verify the sendEmail(/..../) method.
#PrepareForTest({InternalService.InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest {
#Mock
private InternalService.Order order;
private InternalService internalService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
internalService = new InternalService();
}
#Test
public void processOrder() throws Exception {
Mockito.when(order.isSuccessful()).thenReturn(true);
PowerMockito.mockStatic(InternalService.InternalUtils.class);
internalService.processOrder(order);
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
}
}
These two lines is where the magic is,
First line tells the PowerMockito framework that it needs to verify the class it statically mocked. But which method it need to verify ??
Second line tells which method it needs to verify.
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
This is code of my class, sendEmail api twice.
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail("", new String[1], "", "");
InternalUtils.sendEmail("", new String[1], "", "");
}
}
public static class InternalUtils{
public static void sendEmail(String from, String[] to, String msg, String body){
}
}
public class Order{
public boolean isSuccessful(){
return true;
}
}
}
As it is calling twice you just need to change the verify(times(2))... that's all.

Easymock - nested void method testing (spying)

How to spy parameter 'param' in nested method during getData() mock testing ?
Is it possible with Easymock 3 ?
Source code
public class ServiceLogic {
public void getData(){
// some business logic
serviceDAO.executeStatement(param);
}
}
Easymock test :
ServiceLogic _serviceLogicMock = EasyMock.createNiceMock(ServiceLogic.class);
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicMock.setServiceDAO(_serviceDAOMock);
//some other method calls -> .execute(...).andReturn(...);
EasyMock.replay(_serviceLogicMock);
//run
_serviceLogicMock.getData();
How to check with EasyMock whether executeStatement() method is called with correct parameter ?!
Your test does seem wrong:
Your unit test is about testing ServiceLogic why do you mock it then ?
Also you don't have any expectations on any interaction with your ServiceDAO mock.
As the question is tagged Mockito, I propose the following solution (minus the imports) that you can adapt to your code :
#RunWith(MockitoJUnitRunner.class)
public class ServiceLogicTest {
#Mock ServiceDAO serviceDAO;
#InjectMocks ServiceLogic serviceLogic;
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
// given
String input = "Some input";
// when
serviceLogic.getDataFrom(input);
// then
verify(serviceDAO).executeStatement("expected param");
}
}
When writing tests, I like to use the BDD (Behavior Driven Development) style to guide me to what I want to test. I encourage you to practice it, you can have look at the wiki page.
So for your question, you should take a look at the verify line, it put the mock in a verification mode, so can actually verify that the method executeStatement is actually called with the argument value "expected param".
If you have more complex parameters, you can use some matchers using the Hamcrest library:
verify(serviceDAO).executeStatement(argThat(hasProperty("propertyName")));
Or you can use a Mockito's ArgumentCaptor in combination with the FEST-Assert library (usually my preferred approach):
ArgumentCaptor<ComplexArgument> argCaptor = ArgumentCaptor.forClass(ComplexArgument.class);
verify(serviceDAO).executeStatement(argCaptor.capture());
assertThat(argCaptor.getValue()).isNotNull().satisfies(myComplexArgumentCondition());
The main idea is to have understandable code, in production code and in test code.
For further reading have a look at the Mockito Javadoc.
Like #Brice, I prefer Mockito to EasyMock, but here's the EasyMock version that is closer to your original example since your example was EasyMock.
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
_serviceDaoMock.executeStatement("expected para"); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
// verifies that the expected calls were made
EasyMock.verify(_serviceDaoMock);
}
}
EasyMock also has argument capture functionality. That would look like this:
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
Capture<ComplexParam> capturedParam = new Capture<ComplexParam>();
_serviceDaoMock.executeStatement(EasyMock.capture(capturedParam)); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
ComplexParam actualParam = capturedParam.getValue();
// make various assertions on actual param
}
}
I think you can see from the two examples why many people prefer Mockito, but if there's some reason you prefer or are mandated to use EasyMock, you can do just about anything you can do with Mockito, just with more lines of code.
This should be possible with jmockit, unless you DAO has final methods. However, this is better and easier done with jMockit:
#Test
public void testMethod(#Mocked final ServiceDAO serviceDAO) {
new Expectations() {{
serviceDAO.executeStatement(expectedOParams);returns(expectedReturnValue)
}};
(new ServiceLogic(serviceDAO)).getData();
}
That's almost complete test save assertions. And it works with final, static, abstract and whatever methods.

Categories

Resources