Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用Mockito模拟任何方法签名_Java_Mockito - Fatal编程技术网

Java 用Mockito模拟任何方法签名

Java 用Mockito模拟任何方法签名,java,mockito,Java,Mockito,嗨,我有一段代码设计得不是很好,但我不是这段代码的所有者,所以我不能更改它 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

嗨,我有一段代码设计得不是很好,但我不是这段代码的所有者,所以我不能更改它

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;}
}
您看到的界面只是为了让我知道
BigCar
QuiteBigCar
皮卡
“是一辆”车。不是很聪明,但这是我必须处理的

现在我有了一个方法,它接收一个Car作为param,并返回一个模拟版本的Car。我希望mock确保每次调用
isVeryBig()
时,无论方法签名如何,它都将返回false。问题是我没有一个适用于所有
isVeryBig()
方法的通用接口;他们都有不同的签名

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;
}
公共汽车模拟MYCAR(汽车){
模拟汽车=模拟汽车;

当(mockedCar.isVeryBig())有几个选项时,按从最不粗糙到最粗糙的顺序排列:

  • 承认在这里模拟一辆汽车和模拟一个可序列化的一样没有意义,并且你应该选择一个要模拟的实现。模拟一辆具体的大轿车或皮卡不会有同样的困难,你可以在几个测试用例中运行几个不同的实现

  • 按照TrustNoOne所描述的,重构到一个通用的正确多态接口,而不是像这里那样使用仿多态性。我知道你可能会束手无策,但接下来遇到这个问题的人可能不会

  • 创建模拟时,您可以执行类似于按名称(而不是按签名)描述匹配方法的操作:

    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);
      }
    };
    
    Car-Car=Mockito.mock(Car.class,新答案(){
    @覆盖公共对象应答(调用锁调用){
    if(invocation.getMethod().getName().equals(“isVeryBig”)){
    返回false;
    }
    //委托给默认答案。
    返回Mockito.RETURNS\u DEFAULTS.answer(调用);
    }
    };
    
    但是,请记住,您的特殊情况(能够向下转换为具有不同签名的多种实现之一)可能需要使用该功能来根据需要进行Java向下转换,这使得整个过程变得棘手和脆弱。您最好使用上述其他解决方案之一


这与mockito无关。如果你通过“car”接口访问对象,你不能调用任何方法而不向下转换,更不用说模拟了……如果我是你,我会创建一个声明方法的
CarFixed
接口,然后使用静态工厂方法创建一个
AbstractCarFixed
,以创建不同的“具体”
Car
s。这样你至少可以模拟
CarFixed
@TrustNoOne我同意这是一个基本的Java问题。但是,使用JMock有一种解决方法。我可以做:mockedCar.stubs().method(“isVeryBig”).will(returnValue(false));所以,是的,这是我现在使用Mockito时面临的一个限制。@fge请记住,有很多Car实现,我无法控制它们。我不是Car实现类的所有者。我无法自己创建工厂方法,因为我无法控制未来将存在的Car实现类型。
mock(Car)
也不会编译。你是在做类似于
mock(car.getClass())
还是
spy(car)
?谢谢@Jeff Bowman你的答案非常完整。不过,我意识到我的问题真的没有办法解决。我喜欢你的上一个黑客版本,我一定会尝试的。