Using custom ArgumentMatcher

Viewed 56

Suppose I have an interface with method named call, which takes the parameter of ServiceRequest. In ServiceRequest there are fields named fieldA and fieldB. I would want to mock the response of calling this method and return different mock response result if only the value of fieldA in ServiceRequest is different.

I have the following codes like follow (with reference to https://www.baeldung.com/mockito-argument-matchers), however it returns null pointer exception. What goes wrong here ?

@Mock
private Service service;

@Test
public void testCustomMatcher() {
    ServiceRequest req1 = new ServiceRequest();
    req1.setFieldA(1);

    ServiceRequest req2 = new ServiceRequest();
    req2.setFieldA(2);

    when(service.call(argThat(new CustomArgMatcher(req1)))).thenReturn("mockResp1");
    when(service.call(argThat(new CustomArgMatcher(req2)))).thenReturn("mockResp2");
}

public class CustomArgMatcher implements ArgumentMatcher<ServiceRequest> {
    private ServiceRequest left;

    public CustomArgMatcher(ServiceRequest s) {
        this.left = s;
    }

    @Override
    public boolean matches(ServiceRequest serviceRequest) {
        return left.getFieldA() == serviceRequest.getFieldA();
    }
}

interface Service {
    String call(ServiceRequest request);
}

public class ServiceImpl implements Service {

    @Override
    public String call(ServiceRequest request) {
        return "sample";
    }
}

public class ServiceRequest {
    private int fieldA;
    private int fieldB;

    public int getFieldA() {
        return fieldA;
    }

    public void setFieldA(int fieldA) {
        this.fieldA = fieldA;
    }

    public int getFieldB() {
        return fieldB;
    }

    public void setFieldB(int fieldB) {
        this.fieldB = fieldB;
    }
}
1 Answers

I see two problems:

  1. you didn't call MockitoAnnotations.initMocks() anywhere. Usually this goes into a method annotated with @BeforeAll or @BeforeEach. Probably you just didn't copy it to the example.

  2. An ArgumentMatcher has to behave somehow like equals(...): it must accept also null as an argument without throwing an exception.

See the JavaDoc of matches:

The method should never assert if the argument doesn't match. It should only return false.

Try to use this:

return (null != serviceRequest) && (left.getFieldA() == serviceRequest.getFieldA());

As a null ServiceRequest object never will match anything, it will return false in that case.

Related