JMockit:同时模拟 parent 和 child 类

JMockit: Mock both parent and child classes

这是我尝试实现的结果的略微简化版本,但我认为它说明了问题。

假设我有以下两个 classes,其中一个是另一个的后代:

public class Vehicle {

    protected String name;

    {
        name = "Vehicle";
    }

    public String getName() {
        return name;
    }

}

public class Car extends Vehicle {

    {
        name = "Car";
    }

}

我也有这个测试码:

public class VehiclesTest {

    @Test
    public void checkVehicles(@Mocked final Vehicle vehicleMock,
                              @Mocked final Car carMock) {
        new Expectations() {
            {
                vehicleMock.getName(); result = "mocked vehicle";

                carMock.getName(); result = "mocked car";
            }
        };

        Vehicle aVehicle = new Vehicle();
        System.out.println("Starting a " + aVehicle.getName());

        Vehicle aCar = new Car();
        System.out.println("Starting a " + aCar.getName());
    }
}

希望在控制台输出中看到的是:

Starting a mocked vehicle
Starting a mocked car

然而,实际输出看起来像这样:

Starting a mocked car
Starting a mocked car

我是 JMockit 的新手,所以我 我知道为什么会这样(这是因为 JMockit 会模拟所有祖先 classes一直模拟 class 层次结构,不包括 java.lang.Object).

我怎样才能设定我的期望值以获得我想要的结果?是否可以对同一层次结构中不同 classes 的多个模拟设置期望(即一个是另一个的后代)?

以下测试有效:

@Test
public void checkVehicles(@Mocked Vehicle anyCarOrVehicle) {
    new Expectations() {{
        new Vehicle().getName(); result = "mocked vehicle";
        new Car().getName(); result = "mocked car";
    }};

    assertEquals("mocked vehicle", new Vehicle().getName());
    assertEquals("mocked car", new Car().getName());
}

当然,在这种情况下 API 并不明显。一如既往,最好的办法是尽可能避免嘲笑。特别是,模拟旨在用于模拟和验证 行为 ,而不是 状态 。所以,如果你在嘲笑 "getters",那是一个糟糕的测试方法的强烈信号。