Mockito:调用方法A.a时执行B.b

问题描述 投票:0回答:3

我正在使用 Mockito 进行 JUnit 测试。 所以我想测试的代码中使用了一个给定的 A 类:

class A{

    public A(){}

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

}

我想将方法调用 A.a 替换为具有相同参数和相同类型返回值的另一个方法调用。正如您所看到的,不可能通过扩展类来重写方法 a,因为它是最终的。所以我现在拥有的是另一个 B 类,其方法为 B.b:

class B{

    public B(){}

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

}

现在我想确保每次从代码中调用 A.a 时,都会使用 B.b 的返回值。是否有可能使用 Mockito (类似于

Mockito.when(A.a(x)).thenReturn(B.b(x));
)但使用相同的参数 x 来实现此目的,而不知道 x 的值?

如有任何帮助,我们将不胜感激,提前谢谢您!

java unit-testing junit junit4 mockito
3个回答
22
投票

mockito 模拟通过扩展类并覆盖方法来工作,在您的情况下,这在

A.a(String)
上是不可能的。如果您希望发生这种情况,您必须删除最终修饰符。

现在假设

A.a(String)
不是最终的,你所要求的完全可以用mockito实现:

自 Mockito 1.9.5+ 和 Java 8+ 开始

您可以使用 lambda 表达式,例如:

given(mockA.a(anyString())).willAnswer(i -> i.getArguments()[0]);

其中

i
InvocationOnMock
的实例。

对于旧版本:

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);
         }
    };
}

请注意,这个答案是在电话上写的,可能有拼写错误或名称错误,但您应该知道应该做什么才能实现您想要的目标。

干杯


3
投票

根据 Mockito 限制,不可能覆盖 Mockito 生成的模拟的最终方法。但是您可以使用 Powermock 在运行时破解代码,以便 Mockito 可以完成其工作。


1
投票

基本上我采用了您的设置并用它编写了单元测试。首先弹出的是一条错误消息,明确指出了这一点:

org.mockito.exceptions.misusing.MissingMethodInitationException: when() 需要一个参数,该参数必须是“模拟上的方法调用”。

后来在跟踪中它指出“您对以下任一方法进行存根:final/private/equals()/hashCode() 方法。这些方法不能被存根/验证。”

所以根据 Mockito 的说法,你不能存根最终方法,就是这样。

编辑:所以你必须删除最终修饰符,或者,如果你仍然坚持这个类,请找到另一种方法来解决它。

© www.soinside.com 2019 - 2024. All rights reserved.