Mockito's verify method interferes with doAnswer's checks - java

When using mocks for unit testing, I often encounter the need to check whether a certain method of the mock is invoked with proper arguments. This means that I have to somehow find a way to peek into what gets passed to the method in question. In Spock this can be done using something like:
1 * serviceMock.operate(*_) >> { args ->
def argument = args[0]
assert expectedValue = argument.actualValue
}
With Mockito (and JUnit), the only way I think this can be done is by using doAnswer and verify, something like:
doAnswer(new Answer() {
//check arguments here
}).when(service).operate(any(Data.class));
Then I have to verify that the operation actually gets called with:
verify(service).operate(any(Data.class));
The code above, however, interferes with doAnswer as if it's an actual call to the method in question. How do I work around this so that I can both verify that the method is called, and verify that the arguments it gets are correct?

Mockito verifies argument values in natural java style: by using an equals() method. This is also the recommended way of matching arguments because it makes tests clean & simple.
ArgumentCaptor<Data> argument = ArgumentCaptor.forClass(Data.class);
verify(service).operate(argument.capture());
assertEquals("John", argument.getValue().getDataName());
more refer here
I hope this will be helpful

Related

Test lambda expressions called by dependencies

I am trying to test some code inside lambda expression which is a call back from another class.
class EmailSender {
private EmailBuilder emailBuilder;
public void send() {
String testEmail = emailBuilder.buildEmail("Test Email", bodyContentAppender());
//send testEmail
}
private Consumer<Email> bodyContentAppender() {
//how to test this through JUnit?
return email -> email.appendBody("Body Content");
}
}
interface EmailBuilder {
String buildEmail(String templateName, Consumer<Email> contentAppender);
}
The lambda expression in the method getBodyContent is called from EmailBuilder which is a mocked dependency in the JUnit test for EmailSender. Since I am mocking the behavior of EmailBuilder, the code inside getBodyContentis not called from tests. How to test such piece?
EDIT:
Capturing the lambda expression through Argument Captors is not a solution in this case as the behavior of EmailBuilder is mocked and the actual methods are not called. Secondly, email.appendBody does some transformations on an object which is passed by an external API and not straightforward to create.
What you are trying to do here is essentially to verify that a factory method did in fact really return the correct object. There is this related question, where the consensus is to not test the result of a factory method beyond verifying that it does indeed return an object of the correct type. The behavior of that object should be tested in the UnitTests for that type.
In an answer to this related question on unit testing lambdas Stuart Marks argues that
If the code in the lambda is complex enough that it warrants testing, maybe that code ought to be refactored out of the lambda, so that it can be tested using the usual techniques.
Now, the real question is: If this was not a lambda, but a concrete class MyBodyContentAppender that implements the functional interface Consumer<Email>, how would you unit test that? What kinds of test would you write for this class?
You would probably write tests to verify that, given an Email, invoking accept() does indeed invoke appendBody() with the appropriate parameters, perhaps that invoking it with a null argument throws a NullPointerException etc. You would possibly not verify that email.appendBody() works as expected, because that is covered by the tests for Email. You may have to mock Email for these tests if it is difficult to create.
Well, all of these tests can also be performed for the lambda. Your problem is that the factory and the type of the created object are both private, so from the perspective of your test, the only way to access that object is via the parameter passed to the (mocked) emailBuilder.buildEmail().
If you use Mockito for mocking the emailBuilder, you could capture the arguments to this method via ArgumentCaptors (see 15. Capturing arguments for further assertions (Since 1.8.0)), I'm sure other mocking libraries provide similar functionality.
Most mocking frameworks allow you to check arguments that are used when invoking methods on mocked object. Respectively, you can capture them.
So:
acquire the parameter passed
simply invoke the "code" that it represents, and check if that makes the expected updates to an Email object you provided.
It will be easier to test if you actually supply the body content as an argument, and make sure the method is public. If you intend to keep the method as private, then you should test the public method calling it.
public Consumer<Email> getBodyContent(String body) {
//how to test this through JUnit?
return email -> email.appendBody(body);
}
Then you can test it as
#Test
public void testGetBodyContent(){
.... //send different arguments and assert
....
}
So when you want to unit test your code you must ensure that it's doing one job at a time. You method is named as getBodyContent but seems like is supposed to do no more work than appending to email body. Hence, you could pull out this method to be public.
Now you could pass the body and get the content.
#Test
public void testGetBodyContent(){
consumer<Email> consumer = EmailSender.getBodyContent();
assertEquals("Email Content", consumer.accept(<mocked Email object>).getBody())
}

Java unit test check if method is invoked without executing it

I have to test a method which invokes two void methods. I just want to check if the two void methods are invoked or not, but the method must be stubbed.
How do I do it? I tried to implement it using Mockito doThrow method, but not success.
doThrow(new RuntimeException()).when(mockedClass).methodName();
Wanted but not invoked: error
How do I solve my problem?
You can verify only calls in mocked stuff, e.g.
Foo bar = Mockito.mock(Foo.class);
ClassToTest testInstance = new ClassToTest(bar);
testInstance.doStuff();
Mockito.verify(bar, times(1)).someMethod(); // will pass if someMethod of Foo class was called in scope of testInstance.doStuff()
I'm not really sure that you should check actual method calls by expecting an exception. Could you provide some code/a bit more details about the context?
You actually need to use verifyMethod on Mockito. Here is someone who had the same issue. The example shown mocks the object, injects it and then checks to see if it was called or not.
Mockito : how to verify method was called on an object created within a method?

EasyMock expectations with void methods

I'm using EasyMock to do some unit tests and I don't understand the usage of EasyMock.expectLastCall(). As you can see in my code below, I have an object with a method that returns void getting called in some other object's method. I would think that I have to make EasyMock expect that method call, but I tried commenting out the expectLastCall() invocation and it still works. Is it because I passed EasyMock.anyObject()) that it registered it as an expected call or is there something else going on?
MyObject obj = EasyMock.createMock(MyObject.class);
MySomething something = EasyMock.createMock(MySomething.class);
EasyMock.expect(obj.methodThatReturnsSomething()).andReturn(something);
obj.methodThatReturnsVoid(EasyMock.<String>anyObject());
// whether I comment this out or not, it works
EasyMock.expectLastCall();
EasyMock.replay(obj);
// This method calls the obj.methodThatReturnsVoid()
someOtherObject.method(obj);
The API doc for EasyMock says this about expectLastCall():
Returns the expectation setter for the last expected invocation in the current thread. This method is used for expected invocations on void methods.
This method returns you the handle of expectation through IExpectationSetters; which gives you ability to validate(assert) that your void method was called or not and related behaviors e.g.
EasyMock.expectLastCall().once();
EasyMock.expectLastCall().atLeastOnce();
EasyMock.expectLastCall().anyTimes();
Detailed API of the IExpectationSetters is here.
In your example you are just getting the handle and not doing anything with it hence you don't see any impact of having or removing the statement. It's very same as you call some getter method or declare some variable and don't use it.
You only need EasyMock.expectLastCall(); when you need to further verify anything other than "That the method was called. (same as setting expectation)"
Say you want to verify how many times the method was called so you will add any of :
EasyMock.expectLastCall().once();
EasyMock.expectLastCall().atLeastOnce();
EasyMock.expectLastCall().anyTimes();
Or say you want to throw an exception
EasyMock.expectLastCall().andThrow()
If you don't care then EasyMock.expectLastCall(); is not required and does not make any difference, your statement "obj.methodThatReturnsVoid(EasyMock.<String>anyObject());" is enough for setting up expectation.
You are missing EasyMock.verify(..)
MyObject obj = EasyMock.createMock(MyObject.class);
MySomething something = EasyMock.createMock(MySomething.class);
EasyMock.expect(obj.methodThatReturnsSomething()).andReturn(something);
obj.methodThatReturnsVoid(EasyMock.<String>anyObject());
// whether I comment this out or not, it works
EasyMock.expectLastCall();
EasyMock.replay(obj);
// This method calls the obj.methodThatReturnsVoid()
someOtherObject.method(obj);
// verify that your method was called
EasyMock.verify(obj);

How to stub get/set of simple types

I am new to Mockito and I was wondering how I could stub a get/set pair.
For example
public interface Order {
public short getStatus();
public void setStatus(short status);
}
How can I make them behave properly:
if somewhere in a test I invoke setStatus(4); I would like getStatus() to return 4. How can this be done?
Are you stubbing or mocking?
The difference is whether you are verifying behaviour or providing data for a test. You say:
if somewhere in a test I invoke setStatus(4); I would like getStatus() to return 4.
this implies both at the same time. You either want to verify that setStatus() was called with an argument 4.
verify(mockObject).setStatus(4);
or you want to set your mock object to return 4 when getStatus() is called.
when(mockObject.getStatus()).thenReturn(4);
Mockito has some tutorials which explain how to use it for each situation. I suspect you could do both in your test (but have not checked) but this would be a smell to me, as you should ideally only be checking mocking a single thing in your test, everything else should be stubbed. But, as ever, context is everything and so it may be that you need to stub one part of your object so you can verify the behaviour of another part, in which case it would be fine.
Follow the AAA syntax and arrange your test (ie do the setup and have the when clause) then act (ie call the method on the object under test) then do your asserts (ie have your verify statements)
EDIT
it seems that in the newer versions (1.8+) of mockito it may be possible to do what you want, although it is not recommended. You can use a Spy to create a partial mock of an object. In this case you should be able to create a Spy of your actual object, leave the getStatus() and setStatus() methods un-stubbed (so they are actually called and used) and just stub out the other methods (or just verify they were called presumably). You can read about it in section 13 Spying on real objects on this page.
You can set the behavior of the setStatus method so that it updates the behavior of the getStatus method, as follows:
Mockito.doAnswer(invocation -> {
short status = invocation.getArgumentAt(0, Short.class);
Mockito.when(mockOrder.getStatus()).thenReturn(status);
return null;
}).when(mockOrder).setStatus(Mockito.anyShort());

Getting exception from EasyMock's "nice mock" with a debugger attached

(Disclaimer - EasyMock newb)
According to the documentation (and this post), if I wanted to use EasyMock to generate stub objects, I should use EasyMock.createNiceMock(). A "nice mock" is actually a stub - i.e an object that doesn't participate in validation, just returns values.
However, the following snippet fails for me with an IllegalStateException("missing behavior definition for the preceding method"), on the second foo.translate() line.
Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo); // added this line
foo.translate("a", "b");
foo.translate("a", "b"); // only the second calls throws an exception
Can anyone explain this, or rather tell me how to use EasyMock to create stubs with zero verbosity (o(number_of_exercised_mock_methods)).
Edit - I've noticed that I'm getting these errors almost always when a debugger is attached, but never when it isn't attached. Any idea how that may be related?
Complementing on Jeff's answer.
From EasyMock's method createNiceMock javadoc:
Creates a mock object that implements the given interface, order checking
is disabled by default, and the mock object will return 0,
null or false for unexpected invocations.
A mock object created by this method don't need any configuration (expected invocations). You just have to create it and "replay it". Example:
ComplicatedObject stub = EasyMock.createNiceMock();
replay(stub);
Any method call is allowed on the created stub (it won't throw an Exception), and they will always return the default value (0, null or false). If you set up an specific invocation expectation, then you'll have to configure it's return value or you'll get an error (that's your case).
If you want to restrict which methods can be executed (making the test fail if an unexpected method is called), them I'm afraid you'll have to create a regular mock, set up every invocation expectation and a return value for each of those.
If your translate method returns a value, you need to setup an expectation for it.
expect(foo.translate("a","b")).andStubReturn(retVal);
You need to call EasyMock.replay(foo). Before you do that your mock object is in a "record state". From EasyMock documentation:
In the record state (before calling
replay), the Mock Object does not
behave like a Mock Object, but it
records method calls. After calling
replay, it behaves like a Mock Object,
checking whether the expected method
calls are really done.
If you with to create a stub object just call createNiceMock followed by replay:
Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo);
foo.translate("a", "b");
foo.translate("a", "b");

Categories