Mock Void type in Mockito - mockito

Say Foo is the class we mock and Foo has a method named Foo.bar() which returns type Void (not void). How can we use Mockito to mock this method?
Not sure whether returning null in this case would be the best solution.

Because Void is final and not instantiable, there is no instance you could ever return. In production, that method can only return null (if it returns at all), and that should hold true in your tests as well.
Note that Mockito will return null by default for methods that return Object instances other than collections and primitive wrappers, so you should only need to stub a method that returns Void if you need to override a spied method:
// Spy would have thrown exception
// or changed object state
doReturn(null).when(yourSpy).someMethodThatReturnsVoid();
Or throw an exception:
// Throw instead of returning null by default
when(yourMock.someMethodThatReturnsVoid()).thenThrow(new RuntimeException());
Or react with an Answer:
when(yourMock.someMethodThatReturnsVoid()).thenAnswer(new Answer<Void>() {
#Override public void answer(InvocationOnMock invocation) {
// perform some action here
return null;
}
}

Related

Map is not getting populated for ArgumentMatcher object

I am trying to mock an external call along with an ArgumentMatcher to match the input values to the request. But when I trying to fetch the map from the ArgumentMatcher object, it gives me a null value.
Mockito.when(
dynamoDbMapper.scanPage(eq(ABC.class), argThat(new ArgumentMatcher<DynamoDBScanExpression>() {
#Override
public boolean matches(Object argument)
{
DynamoDBScanExpression scanExp = (DynamoDBScanExpression) argument;
Assert.assertEquals("5", scanExp.getLimit());
Assert.assertEquals("xyz",scanExp.getFilterExpression());
Assert.assertEquals(new HashMap(), scanExp.getExpressionAttributeNames());
return true;
}
}))).thenReturn(prepareScanResponse());
This expression scanExp.getExpressionAttributeNames() should ideally return a map but gives me a null value.
So suppose I have to mock a request whose input contains a map, and then try to implement ArgumentMatcher on that inout object which contains a map as an attribute, how would I do that?
Why not use a #Captor? Captors are used to get record parameters passed to methods. It seems like a cleaner way than to try to misuse a matcher.
#ExtendWith(MockitoExtension.class)
class MarketplaceHttpConnectorImplTest {
#Captor
ArgumentCaptor<DynamoDBScanExpression> scanExpressionCaptor;
#Mock
DynamoMapper dynamoDbMapper; // or something like this
#InjectMocks
MyClassToTest sut; // System Under Test
#Test
public void myTest() {
// prepare mocks
when(dynamoDbMapper.scanPage(eq(ABC.class), any(DynamoDBScanExpression.class)).thenReturn(prepareScanResponse());
// Now call the method to test
sut.methodToCall();
// Verify calls
verify(dynamoDbMapper, times(1)).scanPage(eq(ABC.class), scanExpressionCaptor.capture());
DynamoDBScanExpression param = scanExpressionCaptor.getValue();
// now test what was passed to the method.
assertNotNull(param);
// .....
}
}
Btw: don't mind the JUnit5. It also works in JUnit4. Also, I presumed there was just one value. You can capture multiple values in one #Captor and check all values.

how to match the String... use Mockito and PowerMock

I am studying Mockito and PowerMock recently.
I ran into the following problem
//This method belongs to the Messages class
public static String get(Locale locale, String key, String... args) {
return MessageSupplier.getMessage(locale, key, args);
}
//the new class
#RunWith(PowerMockRunner.class)
#PowerMockIgnore( {"javax.management.*"})
#PrepareForTest({Messages.class, LocaleContextHolder.class})
public class DiscreT {
#Test
public void foo() {
PowerMockito.mockStatic(LocaleContextHolder.class);
when(LocaleContextHolder.getLocale()).thenReturn(Locale.ENGLISH);
PowerMockito.mockStatic(Messages.class);
when(Messages.get(Mockito.any(Locale.class),Mockito.anyString(), Mockito.any(String[].class)))
.thenReturn("123156458");
System.out.print(Messages.get(LocaleContextHolder.getLocale(), "p1"));
System.out.print(Messages.get(LocaleContextHolder.getLocale(), "p1", "p2"));
}
}
the result : null 123156458
why? and how to match the String...
In your first System.out.print statement, you use 2 arguments for the Messages.get method. This is one of the method's overloads that you have not mocked. That's why it returns null. Note that object mocks that have not had their behavior mocked will return null by default.
You would have to mock the Messages.get(Locale, String) method as well if you want it to work
when(Messages.get(Mockito.any(Locale.class),Mockito.anyString()))
.thenReturn("123156458");
Remember, the fact that you have mocked the method that takes the most arguments doesn't mean Mockito understands and mocks the rest of the overloads! You have to mock them as well.
There is no way to mock a method once and automatically mock all of its overloads as far as I know however, there is a way to create a mock object and configure a default response for all of its methods. Check out http://www.baeldung.com/mockito-mock-methods#answer

Mockito: Intercept any methods that return a type

I've an interface like this:
public interface ICustomer extends IEnd<Customer> {
String getId();
ICustomer id(String id);
ICustomer email(String email);
ICustomer description(String description);
}
I need to mock any methods which returns an ICustomer regardless of parameters.
When these methods are called, the self called ICustomer have to be returned.
Any ideas?
To do this you need a custom Answer class:
public class CustomerAnswer implements Answer {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Class retType = invocation.getMethod().getReturnType();
if (ICustomer.class.isInstance(retType)) {
return invocation.getMock();
}
// provide default logic here -- override with "when()" calls.
return null;
}
}
Then create your mock, specifying the default behavior:
Foo mockCustomer = mock(ICustomer.class, new CustomerAnswer());
Add, when() statements for other methods that need to be stubbed.
But as I commented in the OP, be sure you actually want to mock this class before you go thru all the trouble. Only mock when it will make the test code simpler. If you have some simple implementation of the interface that is just a POJO with fluent API (no side-effects, no complicated dependencies or injections), there is probably no need to mock it. Instead use a real instance, because the real instance already returns the original object.
If you need to verify() on the ICustomer object, then use a #Spy of a real instance of a ICustomer.

How to use PowerMockito to verify super method is called

I am testing a legacy code that use inheritance method. I am trying to mock super-method
to verity if the super-method is being call or not.
#RunWith(PowerMockRunner.class)
public class HumanTest {
#Test
public void test() throws NoSuchMethodException, SecurityException {
// 1. arrange
Human sut = PowerMockito.spy(new Human());
PowerMockito.doNothing().when((SuperHuman) sut).run(); // SuperHuman is the parent class
// 2. action
sut.run();
// 3. assert / verify
}
}
public class Human extends SuperHuman {
#Override
public void run() {
System.out.println("human run");
super.run();
}
}
public class SuperHuman {
public void run() {
System.out.println("superhuman run");
}
}
I was expecting that "human run" will be printed. But the actual result was none printed.
PowerMockito.doNothing().when((SuperHuman) sut).run(); // SuperHuman is the parent class
This won't work in your case since PowerMockito will mock method of Human even if you made cast.
I checked your code example and could say that it is possible to suppress invocation of super class method with:
Method toReplace = PowerMockito.method(SuperHuman.class, "run");
PowerMockito.suppress(toReplace);
But it seems that method replacment feature does not work for methods of super class:
createPartialMock should support mocking overridden methods in super classes.
So this does not work:
PowerMockito.replace(toReplace).with(new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Method of superclass has been invoked !");
return null;
}
});
But still you should be able to verify invocation of super method let's say indirectly, by mocking other classes which are invoked in super method only.
For instance check that System.out.println was invoked with "superhuman run" or something like this.

Powermock to mock instance methods called from other executing methods

In this code, i have mocked the one of the ValidateHandlerSoapClient class method which is instantiated and called this method (soapClientSpy.processSoapRequestRespons) in validateMsisdnHandlerIRSpy.validate().So soapClientSpy.processSoapRequestResponse is not working , instead the real method is called.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ValidateMsisdnHandler.class,ValidateHandlerSoapClient.class})
public class Demo {
MessageControl messageControl=PowerMockito.mock(MessageControl.class);
Validate validate=PowerMockito.mock(Validate.class);
ValidateMsisdnHandlerIR validateMsisdnHandlerIRSpy = PowerMockito.spy(new ValidateMsisdnHandlerIR());
ValidateHandlerSoapClient soapClientSpy = PowerMockito.spy( new ValidateHandlerSoapClient());
#Before
public void initialize() throws Exception
{
PowerMockito.when(validate.getAccountId()).thenReturn("0879221485");
PowerMockito.doReturn(true).when(validateMsisdnHandlerIRSpy, "isPrePaid",anyString());
MemberModifier.field( ValidateMsisdnHandlerIR.class, "endDate").set(
validateMsisdnHandlerIRSpy, "10-FEB-2015");
PowerMockito.when(soapClientSpy.processSoapRequestResponse(anyString())).thenReturn(true);
PowerMockito.whenNew(ValidateHandlerSoapClient.class).withNoArguments().thenReturn(soapClientSpy);
}
#Test
public void testValidateMsisdn_Cr6_Roverprempay_Not_Roverpayg() throws Exception{
Response response = validateMsisdnHandlerIRSpy.validate(validate,messageControl);
}
Replace
ValidateHandlerSoapClient soapClientSpy = PowerMockito.spy( new ValidateHandlerSoapClient())
with
ValidateHandlerSoapClient soapClientMock = PowerMockito.mock(ValidateHandlerSoapClient.class)
A spy by default just calls the methods of the underlying regular class. What you want to do is (presumably) nothing when the methods of the soap client are called.
Then of course you will need to make also change:
PowerMockito.whenNew(ValidateHandlerSoapClient.class).withNoArguments().thenReturn(soapClientMock);

Resources