Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito: when Method A.a is called then execute B.b

I'm using Mockito for JUnit tests. So there is a given class A that is used from the code i want to test:

class A{

    public A(){}

    public final String a(String x){
        return "A.a: " + x;
    }

}

and i want to replace the Method call A.a with another method call with the same arguments and same type of return value. As you can see, its not possible to override the method a by extending the class as it is final. So what i have now is another class B with the method B.b:

class B{

    public B(){}

    public String b(String x){
        return "B.b: " + x;
    }

}

Now i want to make sure every time when A.a is called from the code, the return value of B.b is used instead. Is there a possibility to achieve this with Mockito (something like Mockito.when(A.a(x)).thenReturn(B.b(x)); ) but with the same parameter x, without knowing the value of x?

Any help would be appreciated, thank you in advance!

like image 729
user1448982 Avatar asked Aug 23 '12 08:08

user1448982


3 Answers

Well mockito mocks works by extending the class and overriding the method, which in your case is not possible on A.a(String). If you want this to happen you have to remove the final modifier.

Now assuming A.a(String) is not final, what you ask is completely doable with mockito:

given(mockA.a(anyString()).willAnswer(returnOfB(bInstance));

Answer<String> returnOfB(final B bInstance) {
    return new Answer<String>() {
         public String answer(Invocation invocation) {
             String arg = (String) invocation.getActualArguments()[0];
             return bInstance.b(arg);
         }
    };
}

Please note this answer has been written on a phone and might have typo, or wrong names, though you should get the idea of what should be done to achieve what you want.

Cheers

like image 99
Brice Avatar answered Nov 04 '22 11:11

Brice


It isn't possible to override final methods for Mockito-generated mocks, according to Mockito limits. But you can use Powermock to hack code at runtime so that Mockito can do its job.

like image 21
Sergej Zagursky Avatar answered Nov 04 '22 11:11

Sergej Zagursky


Basically I took your setup and wrote a Unit-Test with it. What popped up first was an error message that explicitly stated this:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'.

And later in the trace it states that "you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified."

So according to Mockito you cannot stub final methods, and that's that.

Edit: So you have to either remove the final modifier or, in case you're stuck with this class as it is, find another way around it.

like image 1
Simon Hellinger Avatar answered Nov 04 '22 09:11

Simon Hellinger