为什么Mockito.when(...)。doReturn(...)如果从Mockito.doAnswer(...)调用,则无法正常工作

时间:2016-04-28 07:19:30

标签: java unit-testing mockito

我需要测试一个创建includes对象的方法,并使用Car将其保存在数据库中。另一种方法是创建CarDao对象,但如果Car是mock,那么CarDao将返回car.getUser()而不是正确的null对象。这是我的代码。

User

为什么Mockito.doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocationOnMock) throws Throwable { lastCarId++; Car car = (Car) invocationOnMock.getArguments()[0]; // here car.getUser() returns correct user object car.setId(lastCarId); Mockito.when(carDao.getById(car.getId())).thenReturn(car); return null; } }).when(carDao).persist(Mockito.any()); 返回null?我需要做些什么来获得具有正确carDao.getById(carId).getUser()字段值的完整对象?

更新

user用法:

carDao

下面是代码抛出NullPointerException的Car car = carService.create("car name1", "color", "year", user); // in this method called carDao.persist(...); car.setColor("color2"); carService.findById(car.getId()); // this method calls carDao.getById(carId) // and comapres with authenticated user ID. // But carDao.getById(carId) returns car with user == null 类的一部分。

CarService

感谢。

1 个答案:

答案 0 :(得分:2)

正如我从示例中所理解的那样,您有一些要测试的课程,我们称之为Handler。在此Handler中,您使用CarService来“构建和存储”汽车对象,并在DB中“查找”汽车对象(带有一些User验证)。在CarService中,您使用CarDao来处理数据库 首先:如果您测试Handler类,那么您需要模拟IT OWN依赖项,这意味着您需要模拟CarService,而不是CarService内部的CarDao(不是嵌套依赖项的第二级)。你需要在测试CarService时模拟CadDao,它应该与CarHandlerTest分开测试。

第二:我模拟你的例子并且它有效,请参阅下面的代码。

public class User {} //simple user just to verify not null

public class Car {
    private Long id;
    private User user;
    //getters ans setters
}

public class CarDao { //with stub methods because we will mock it
    public void persist(Car car) {}
    public Car getById(Long id) {return new Car();}
}

public class CarHandler {
    private CarService carService; //with setter
    public void foo() { // we will test this method
        User user = new User(); //it's like your example but without additional fields (like color)
        Car car = carService.create(user); // here we build and store new car
        Car sameCar = carService.findById(car.getId());
        assert car == sameCar;
    }
}

public class CarService {
    private CarDao carDao; //with setter
    public Car create(User user) {
        Car car = new Car();
        car.setUser(user);
        carDao.persist(car); //here car should get id
        return car;
    }

    public Car findById(Long id) {
        Car car = carDao.getById(id);
        User user = car.getUser(); //this user should be not null in test
        assert user != null; //this assert for verify user
        return car;
    }
}

最有趣的部分 - 测试。

public class CarHandlerTest {
    static long lastCarId = 5;
    private CarHandler carHandler = new CarHandler();
    private CarService carService = new CarService();
    private CarDao carDao;

    @Test
    public void testFoo() throws Exception {
        carDao = Mockito.mock(CarDao.class);
        carService.setCarDao(carDao);
        carHandler.setCarService(carService);

        Mockito.doAnswer(new Answer<Void>() { //I copy it from your example
            @Override
            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
                lastCarId++;
                Car car = (Car) invocationOnMock.getArguments()[0];
                // here car.getUser() returns correct user object
                car.setId(lastCarId);
                Mockito.when(carDao.getById(car.getId())).thenReturn(car);
                return null;
            }
        }).when(carDao).persist(Mockito.any());

        carHandler.foo();
    }
}

您也可以从Car方法返回foo()并验证测试中的所有内容。