gpt4 book ai didi

java - org.mockito.exceptions.misusing.MissingMethodInvocationException

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:48:33 29 4
gpt4 key购买 nike

我在运行 Junit 测试时遇到以下异常。

org.mockito.exceptions.misusing.MissingMethodInvocationException:

when() requires an argument which has to be 'a method call on a mock'. For example:

   when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:

  1. you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified.
  2. inside when() you don't call method on mock but on some other object.
  3. the parent of the mocked class is not public. It is a limitation of the mock engine.

以下是我的代码,在第二个 when 语句中抛出了异常。我不认为我的测试代码没有违反异常声明的内容。我花了一段时间,但想不通。有人可以帮忙吗?我需要测试的是 getPermProducts 方法。在 getPermProducts 方法中,我想忽略 isTempProduct 方法。所以,当 p1 出现时,我希望它返回 false,当 p2 出现时,我希望它返回 true 等等。

@Named(ProductManager.NAME)
public class ProductManager {

@Resource(name = ProductService.NAME)
private ProductService productService;

public List<Product> getPermProducts(Set<Product> products) {
Iterator<Product> it = products.iterator();
List<Product> cProducts = new ArrayList<Product>();
Product p;
while (it.hasNext()) {
p = it.next();
if (!isTempProduct(p)) {
cProducts.add(p);
}
}
return cProducts;
}

public Boolean isTempProduct(Product product) {
if (product instanceof PermProduct) {
return false;
}
Set<ProductItems> pItems = product.getProductItems();
if (pItems.isEmpty()) {
return false;
}
Iterator<ProductItem> itr = pItems.iterator();
while (itr.hasNext()) {
if (itr.next() instanceof TempItem) {
return true;
}
}
return false;
}

public Product getProduct(Integer productId) {
Product p = productService.getProduct(productId);
return p;
}

}



@RunWith(MockitoJUnitRunner.class)
public class ProductManagerTest {


@InjectMocks
private ProductManager mockProductManager;
@Mock
private ProductService mockProductService;//not being used here

private static final Integer PRODUCT_ID_1 = 1;
private static final Integer PRODUCT_ID_2 = 2;

@Test
public void getProduct(){
Product p1 = mock(PermProduct.class);
p1.setProductId(PRODUCT_ID_1);
when(mockProductManager.getProductId()).thenReturn(PRODUCT_ID_1);
when(mockProductManager.isTempProduct(p1)).thenReturn(false);
Product p2 = mock(TempProduct.class);
p2.setProductId(PRODUCT_ID_2);
when(mockProductManager.isTempProduct(p2)).thenReturn(true);
List<Product> products = Mock(List.class);
products.add(p1);
products.add(p2);
Iterator<Product> pIterator = mock(Iterator.class);
when(prodcuts.iterator()).thenReturn(pIterator);
when(pIterator.hasNext()).thenReturn(true, true, false);
when(pIterator.next()).thenReturn(p1, p2);
asserEquals(1, mockProductManager.getPermProducts(products).size());

}

}

解决方案:我根据 enterbios 的回答更新了我的测试。我使用了部分模拟,但正如 enterbios 所建议的那样,我们应该避免它,但有时我们需要它。我发现我们可以同时拥有非模拟类和部分模拟类。

@RunWith(MockitoJUnitRunner.class)
public class ProductManagerTest {

@InjectMocks
private ProductManager productManager;//not being used here
@Mock
private ProductService mockProductService;//not being used here

@Spy
private OtherService other = new OtherService();//not being used here

@InjectMocks
final ProductManager partiallyMockedProductManager = spy(new ProductManager());

private static final Integer PRODUCT_ID_1 = 1;
private static final Integer PRODUCT_ID_2 = 2;

@Test
public void getProduct() {
Product p1 = new PermProduct();
p1.setProductId(PRODUCT_ID_1);
Product p2 = new Product();
p2.setProductId(PRODUCT_ID_2);
List<Product> products = new ArrayList<Product>();
products.add(p1);
products.add(p2);

doReturn(false).when(partiallyMockedProductManager).isTempProduct(p1);
doReturn(true).when(partiallyMockedProductManager).isTempProduct(p2);
assertEquals(1, partiallyMockedProductManager.getPermProducts(products).size());
verify(partiallyMockedProductManager).isTempProduct(p1);
verify(partiallyMockedProductManager).isTempProduct(p2);
}
}

最佳答案

您的 mockProductManager 实际上不是一个 mock,而是 ProductManager 类的一个实例。你不应该 mock 被测试的对象。从测试对象中模拟某些方法的方法是使用 spy ,但我建议您不要使用它们,或者甚至不要考虑它们,除非您正在与一些丑陋的遗留代码作斗争。我认为您的第二个“何时”应该替换为断言,例如:

assertFalse(mockProductManager.isTempProduct(p1));

因为在此测试中您真正想要检查的是 productManager.isTempProduct(p1) 是否对所有 PermProduct 实例返回 false。要验证某些方法调用/对象状态的结果,您应该使用断言。为了让你的断言生活更轻松,你可以看看一些有用的库,比如 Hamcrest 或 FEST (http://docs.codehaus.org/display/FEST/Fluent+Assertions+Module)。我认为 FEST 对于初学者来说更简单。

关于java - org.mockito.exceptions.misusing.MissingMethodInvocationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22873419/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com