web-dev-qa-db-de.com

Stubbing einer Methode, die Class <T> als Parameter mit Mockito übernimmt

Es gibt eine generische Methode, die eine Klasse als Parameter verwendet, und ich habe Probleme, sie mit Mockito zu unterdrücken. Die Methode sieht so aus:

public <U extends Enum<U> & Error, T extends ServiceResponse<U>> T validate(
    Object target, Validator validator, Class<T> responseClass,
    Class<U> errorEnum);

Gott ist schrecklich, zumindest für mich ... Ich könnte mir vorstellen, ohne es zu leben, aber der Rest der Code-Basis verwendet es gerne ...

Ich wollte in meinem Unit-Test diese Methode stubben, um ein neues leeres Objekt zurückzugeben. Aber wie mache ich das mit Mockito? Ich habe es versucht:

when(serviceValidatorStub.validate(
    any(), 
    isA(UserCommentRequestValidator.class), 
    UserCommentResponse.class, 
    UserCommentError.class)
).thenReturn(new UserCommentResponse());

da ich jedoch Matcher und Rohwerte mische und abgleiche, erhalte ich "org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Ungültige Verwendung von Argument-Matchern!"

40
Peter Perháč

Das Problem ist, dass Sie in einem verspotteten Aufruf keine Argumentvergleicher und echte Argumente kombinieren können. Also mach lieber das: 

when(serviceValidatorStub.validate(
    any(),
    isA(UserCommentRequestValidator.class),
    eq(UserCommentResponse.class),
    eq(UserCommentError.class))
).thenReturn(new UserCommentResponse());

Beachten Sie die Verwendung des eq()-Argument-Matchers zum Abgleichen von Gleichheit.

siehe: https://static.javadoc.io/org.mockito/mockito-core/1.10.19/org/mockito/Matchers.html#eq(T)

Sie können auch das same()-Argument-Matcher für Class<?>-Typen verwenden. Dies entspricht der gleichen Identität wie der ==-Java-Operator.

75
Jesse

Um nur in demselben Thread abzuschließen, wenn jemand eine Methode stubb machen möchte, die eine Klasse als Argument akzeptiert, sich aber nicht für den Typ interessiert oder viele Typen auf dieselbe Art und Weise stubben müssen, hier eine andere Lösung:

private class AnyClassMatcher extends ArgumentMatcher<Class<?>> {

    @Override
    public boolean matches(final Object argument) {
        // We always return true, because we want to acknowledge all class types
        return true;
    }

}

private Class<?> anyClass() {
    return Mockito.argThat(new AnyClassMatcher());
}

und dann anrufen 

Mockito.when(mock.doIt(this.anyClass())).thenCallRealMethod();
2
Ash

Nizza @ Ash. Ich habe Ihren generischen Klassen-Matcher zur Vorbereitung unten verwendet .. Dies kann verwendet werden, wenn ein Modell eines bestimmten Typs vorbereitet werden soll.

private Class<StreamSource> streamSourceClass() {
    return Mockito.argThat(new ArgumentMatcher<Class<StreamSource>>() {

        @Override
        public boolean matches(Object argument) {
            // TODO Auto-generated method stub
            return false;
        }
    });
}

Verwendungszweck:

    Mockito.when(restTemplate.getForObject(Mockito.anyString(), 
            **streamSourceClass(),**
            Mockito.anyObject));
0
user3777313