gpt4 book ai didi

java - 使用 Mockito 模拟任何方法签名

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:21:29 25 4
gpt4 key购买 nike

您好,我有这段代码设计得不是很好,但我不是这段代码的所有者,所以我无法更改它。

public interface Car{ // This is a marker interface. }

public class BigCar implements Car{
public boolean isVeryBig(){
return true;}
}

public class QuiteBigCar implements Car{
public boolean isVeryBig(boolean withHatchBack){
return true;}
}

public Pickup implements Car{
public boolean isVeryBig(boolean withHatchBack, boolean withRoofRack){
return true;}
}

您看到接口(interface)的存在只是为了让我知道 BigCarQuiteBigCarPickup"is"Car。不是很聪明,但这就是我必须处理的。

现在我有一个方法可以接收汽车作为参数,并将返回汽车的模拟版本。我希望 mock 确保每次调用 isVeryBig() 时,它都会返回 false 而不考虑方法签名。问题是我没有所有 isVeryBig() 方法的通用接口(interface);他们都有不同的签名。

public Car mockMyCar(Car car){

Car mockedCar = mock(car);

when(mockedCar.isVeryBig()) <-- This wont work since the method doesn't exist on the interface

return mockedCar;
}

是的,我可以将 Car 转换为它们的子类,但这对我来说不是一个选项,因为有太多实现 Car 的类,对所有实现进行 instanceOf 检查会使代码非常糟糕,而且我无法控制新的Car 在未来的实现。

有什么想法吗?

最佳答案

一些选项,按照从最少到最多的顺序:

  • 承认在这里模拟 Car 与模拟 Serializable 一样毫无意义,并且您实际上应该选择一个实现来模拟。您不会在模拟具体的 BigCar 或 Pickup 时遇到同样的麻烦,并且您可以在几个测试用例中运行几个不同的实现。

  • 如 TrustNoOne 所述,重构为通用的适当多态接口(interface),而不是像您在此处使用的那样使用 ersatz 多态性。我知道你可能束手无策,但下一个偶然发现这个问题的人可能不会。

  • 您可以通过 supplying a default Answer 执行与您所描述的类似的操作——按名称而不是签名匹配方法。创建模拟时:

    Car car = Mockito.mock(Car.class, new Answer<Object>() {
    @Override public Object answer(InvocationOnMock invocation) {
    if (invocation.getMethod().getName().equals("isVeryBig")) {
    return false;
    }
    // Delegate to the default answer.
    return Mockito.RETURNS_DEFAULTS.answer(invocation);
    }
    };

    不过请记住,您的特定情况(能够向下转换为具有不同签名的多种实现之一)可能需要使用 extraInterfaces根据需要让 Java 向下转型的功能,这使得整个事情变得棘手和脆弱。您最好改用上述其他解决方案之一。

关于java - 使用 Mockito 模拟任何方法签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21939246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com