2016-04-28 36 views
1

我需要測試一種方法,該方法會創建Car對象並使用CarDao保存它在數據庫中。另一種方法獲取Car對象,但如果CarDao是模擬,則car.getUser()返回null而不是正確的User對象。這是我的代碼。爲什麼Mockito.when(...)。doReturn(...)無法正常工作,如果它從Mockito.doAnswer調用(...)

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()); 

爲什麼carDao.getById(carId).getUser()返回null?我需要做什麼才能獲得正確的user字段值的對象?

更新

carDao用法:

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類,其中代碼引發NullPointerException異常的一部分。

// carService.findById(...) method 
public Car findById(Car id) { 
    Car car = carDao.getById(id); 
    User carUser = car.getUser(); // returns null 
    User currentUser = accountService.getAuthenticatedUser(); // returns correct user object 
    if (!carUser.getId().equals(currentUser.getId())) { // throws NullPointerException 
     return null; 
    } 
    return car; 
} 

謝謝。

+1

你的'用戶'對象是否設置在你從'invocationOnMock.getArguments()[0];'檢索到的'car'對象中?如果沒有,需要檢查它爲什麼爲空 – Draken

+0

@Draken,是'用戶'對象設置在'car'對象中我從'invocationOnMock.getArguments()[0];' –

+0

中檢索到'你在什麼時候檢查' carDao.getById(carId).getUser()'屬性?我們可以看到你的部分在哪裏被稱爲? – Draken

回答

2

正如我從例子中所瞭解的,你有一些你想測試的類,我們稱之爲Handler。在此處理程序中,您使用CarService來「建立和存儲」汽車對象,並在數據庫中「查找」汽車對象(有一些User驗證)。在CarService中,您使用CarDao來處理數據庫。因此,首先:如果您測試Handler類,那麼您需要嘲笑IT OWN依賴關係,這意味着您需要模擬CarService,但CarService不在CarService內(而不是第二層嵌套依賴關係)。無論何時測試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(); 
    } 
} 

您也可以從foo()方法返回Car和驗證測試的一切。

相關問題