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.