這個問題在這里已經有了答案: 單元測驗中的 ArgumentCaptor 使用 2 個答案 3天前關閉。
我查看了幾個使用示例,例如Using Mockito ArgumentCaptor,但我對以下場景的正確用法感到困惑:
這是我要測驗的方法:
@Override
public ProductDTO create(Product product, UUID uuid) {
// code omitted for brevity
final Product saved = productRepository.save(product);
final Currency currency = currencyService.getCurrencyByUuid(uuid);
return new ProductDTO(saved, currency);
}
我的測驗方法:
@RunWith(MockitoJUnitRunner.class)
public class ProductServiceImplTest {
@Mock
private ProductRepository productRepository;
@Mock
private CurrencyService currencyService;
@InjectMocks
private ProductServiceImpl productService;
@Captor
private ArgumentCaptor<Product> productCaptor;
@Test
public void test_create() {
UUID uuid = UUID.fromString("00000000-0000-0000-0000-000000000001");
UUID productUuid = UUID.fromString("00000000-0000-0000-0000-000000000222");
Currency currency = Currency.getInstance("EUR");
Product product = new Product();
productCostBySite.setProductUuid(productUuid);
// 1. prepare the values
when(productRepository.save(productCaptor.capture())).thenReturn(product);
when(currencyService.getCurrencyByUuid(uuid)).thenReturn(currency);
// 2. call the service method that is tested
ProductDTO result = productService.create(product);
// 3. Check if the captured value is the expected one
Product value = productCaptor.getValue();
assertEquals(productUuid, value.getProductUuid());
assertEquals(currency.getCurrencyCode(),
result.getCurrency().getCurrencyCode());
}
}
以下是問題(數字也是測驗方法的注釋編號):
1.我productRepository.save使用回傳值測驗方法ArgumentCaptor,currencyService.getCurrencyByUuid(uuid)因為它不是存盤庫呼叫。真的嗎?
2.我呼叫了服務方法,但在某些示例verify中使用了方法。我不確定我是否需要在verify這個例子中使用方法?任何的想法?
3.我將回傳的值用于服務,并將捕獲的值用于存盤庫。這是一個正確的方法嗎?
uj5u.com熱心網友回復:
對我來說,你根本不需要ArgumentCaptor這里,你已經模擬了你的存盤庫并且你的方法 ( create) 已經回傳了一個ProductDTO. 因此,測驗這種方法是微不足道的。
Product emptyProduct = new Product();
Product productWithValues = new Product();
productWithValues.set... // set the values you want to assert when(productRepository.save(Mockito.eq(emptyProduct))).thenReturn(productWithValues);
Currency currency = new Currency();
currency.set... // more fields you would like to assert
UUID uuid = UUID.randomUUID();
when(currencyService.getCurrencyByUuid(uuid)).thenReturn(currency);
ProductDTO result = create(emptyProduct, id);
Mockito.assertEquals(result.getCurrency().getCurrencyCode(), currency.getCurrencyCode());
Mockito.assertEquals(result.getProduct().getProductUuid(), product.getProductUuid());
作為免責宣告,我沒有編譯上面的代碼,但你應該明白了。
uj5u.com熱心網友回復:
Eugene 是對的,您不需要ArgumentCaptor. 回答何時需要它的問題:如果您想驗證在您的方法之前或之后您無權訪問的事務物件的值。
例如,在
boolean createAndSave(String productName) {
Product p = new Product(productName);
return repository.save(p);
}
您無權訪問已創建Product但想驗證它是否已正確創建。為此,您可以捕獲它:
ArgumentCaptor<Product> savedCaptor = ArgumentCaptor.forClass(Product.class);
service.createAndSave("name");
verify(repository).save(savedCaptor.capture()); // get the product being saved
Product saved = savedCaptor.getValue();
assertEqual("name", saved.getName());
現在,您確保該存盤庫用于保存具有您為服務提供的名稱的產品。
在您的情況下,您可以只使用when(repository.save(any()).thenReturn(product)您提前創建的產品。
uj5u.com熱心網友回復:
根據檔案,使用 ArgumentCaptor 的推薦方法不是用于存根,而是用于驗證:
verify(productRepository).save(productCaptor.capture())
引數捕獲器對于提供的create(...)實作看起來并不是特別有用,因為如果您保存的物件與您傳遞給被測方法的物件完全相同,那么將實際參??數傳遞給when(...)僅用于模擬就足夠了:
when(productRepository.save(product)).(...)
根據我的經驗,引數捕獲器更多地用于以下情況:引數沒有顯式傳遞給被測方法(用你的例子想象這productRepository#save不是保存傳遞給的產品create(...),而是保存在create(...)自身內部創建的一些新實體)或者當方法under test 更改了一些未包含在物件equals(...)方法中的欄位。
驗證應該用于模擬物件,以斷言實際方法呼叫發生了特定數量的所需引數。
具體回答您的問題:
- 如果傳遞給 的產品與傳遞給 的
productRepository#save產品相同,則不需要引數捕獲器create(...),因為您when(productRepository.save(productCaptor.capture()))只需替換為when(productRepository.save(product)) - 測驗下的方法應該在沒有的情況下呼叫
verify(...),verify 旨在與模擬一起使用以斷言呼叫了特定的模擬方法 - 總體方法是正確的
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/406792.html
標籤:
上一篇:AngularHTTP攔截器測驗失敗,而攔截器作業正常
下一篇:顫動凍結:等于物件的型別不同
