I am writing unit tests for my application and I was wondering if it is possible for the Mockito framework to affect an object that is passed into a method that returns void of a mocked class. For instance, calling a mocked validation class that contains a method that returns void but tracks various changes and metadata via an object passed in as an argument. .
public GetCartItemsOutput getCartItems(GetCartItemsInput getCartItemsInput) {
CartItemsFilter cartItemsFilter = new CartItemsFilter();
validator.validateCartItemsInput(getCartItemsInput, cartItemsFilter); ...
I mocked the validator class for my other tests but for this one I need mock the changes to the cartItemsFilter object which I do not know how to do.
Mockito provides following methods that can be used to mock void methods. doAnswer() : We can use this to perform some operations when a mocked object method is called that is returning void. doThrow() : We can use doThrow() when we want to stub a void method that throws exception.
Your modified program can ask for user input, call the function, then print the output. A testing framework can supply the input from a list of inputs to test, and check the outputs against the expected values. To test as-is, you'd have to intercept the input and output streams.
Void functions are created and used just like value-returning functions except they do not return a value after the function executes. In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value.
While doing unit testing using junit you will come across places where you want to mock classes. Mocking is done when you invoke methods of a class that has external communication like database calls or rest calls.
The answer is yes, you can, and there are basically two levels of doing this, based on the need of your test.
If you merely want to test the interaction with the mocked object, you can simply use the verify()
method, to verify that the void method was called.
If your test genuinely needs the mocked object to modify parameters passed to it, you will need to implement an Answer
:
EDITED to show proper form of using Answer with void method
doAnswer(new Answer() {
@Override
Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
return null; // void method, so return null
}
}).when(mock).someMethod();
In Java 8+, the above is simplified with a lambda:
doAnswer(invocation-> {
Object[] args = invocation.getArguments();
((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
return null;
}).when(mock).someMethod();
To add to Kevin Welker's answer, if your MyClass is a custom class, then define a equals/hashcode method in it, so that Mockito can use it to match to the method call exactly.
In my case, "MyClass" was in a third-party API, so I had to use the method "any" as below -
doAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
((MyClass)args[0]).myClassSetMyField(NEW_VALUE);
return null; // void method, so return null
}
}).when(mock).someMethod(any(MyClass.class));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With