首页 > 解决方案 > 使用 Mockito 测试方法的正确方法是什么?

问题描述

我目前正在尝试使用 Mockito 测试一种方法,但我坚持使用某种方法。

例如,有名为 Car 和 CarSystem 的类。

car 类包含两个参数,Name(String) 和它的 License Plate(String) 以及它们的 getter/setter 方法。

我尝试使用 Mockito 测试的方法是一个名为 addCar 的方法,它位于 CarSystem 类中。

汽车系统类:

private final List<Car> cars= new ArrayList<>();

public Car addCar(String name, String plateNumber) throws IllegalStateException {
        Car clash = getCar(plateNumber);
        if (null != clash) throw new IllegalStateException("Car with that Number already exists");

        Car car = new Car(name, plateNumber);
        cars.add(car);

        return car;
    }


public Car getCar(String match) {
        for (Car car: cars) {
            if (car.getPlateNumber().equals(match)) return car;
        }

        return null;
    }

我要测试的是两件事:

  1. 当汽车列表中已经存在车牌号的汽车时,它会成功抛出 IllegalStateException 异常。

  2. 它成功地将汽车添加到列表中。

我只使用 JUnit 所做的是:

@Test
    public void testAddCar_ThrowingException() {

        try {

            CarSystem sys = new CarSystem();
            Car car = sys.addCar("1234", "Toyota123");
            Car car1= sys.addCar("1234", "Honda123");
            Assert.fail();
        } catch(IllegalStateException e) {
            System.out.println(e);
        }
    }

@Test
    public void testAddCar() {

            CarSystem sys = new CarSystem();
            Car car = sys.addCar("1234", "Toyota123");
            Assert.assertEquals(sys.getCar(1234).getName(), "Toyota123");
    }

但我不知道如何使用 Mockito 来测试它们......谁能帮助我或给我一个提示?

PS)我可以自由更改 Mockito 测试的课程内容。

标签: javamockingmockito

解决方案


我不会创建Car要添加到方法中的方法,而是将其作为参数传入,即

interface CarService {
  Car addCar(Car toAdd);
  Car getCar(String plateNumber);
}

由于您正在测试服务本身,因此您无法模拟它 - 只有汽车。由于Car您访问的唯一数据是getPlateNumber,因此测试看起来像这样:

class ScratchTest {
    private CarService sut;

    @Before
    public void before() {
        sut = new CarService();
    }

    @Test
    public void addSucceeds() {
        String plateNumber = "new";
        Car toAdd = mock(Car.class);
        when(toAdd.getPlateNumber()).thenReturn(plateNumber);
        Car added = sut.addCar(toAdd);

        // assert return value
        assertSame(toAdd, added);
        // assert car now available via get
        Car stored = sut.getCar(plateNumber);
        assertSame(toAdd, stored);
    }

    @Test(expected = IllegalArgumentException.class)
    public void addFails() {
        Car existing = mock(Car.class);
        String plateNumber = "existing";
        when(existing.getPlateNumber()).thenReturn(plateNumber);
        sut.addCar(existing);
        Car toAdd = mock(Car.class);
        when(toAdd.getPlateNumber()).thenReturn(plateNumber);

        sut.addCar(toAdd);
    }
}

您不能真正独立地测试 add 和 get ,因为它们彼此不变量: 1. 如果add使用具有新车牌号的汽车调用,则后续get给定的车牌号将检索它,并且 2.get使用车牌调用if之前调用过的 aCar的编号add,它将被返回。


推荐阅读