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

2019-02-21 09:48发布

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!

3条回答
放荡不羁爱自由
2楼-- · 2019-02-21 10:04

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.

查看更多
不美不萌又怎样
3楼-- · 2019-02-21 10:04

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.

查看更多
别忘想泡老子
4楼-- · 2019-02-21 10:08

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

查看更多
登录 后发表回答