我有一个包含公共静态方法getProduct(String name)
的课程:
public class ProductManager {
public static Product getProduct(String name) {
Product prod = findProduct(name);
return prod;
}
}
另一个CustomerService
班级使用上述ProductManager
:
public class CustomerService {
...
public void handleProduct() {
Product appleProd = ProductManager.getProduct("apple");
doHandle(appleProd);
}
}
我在handleProduct()
课程中单元测试CustomerService
方法。我使用mockito来模拟测试中的ProductManager.getProduct("apple")
部分:
public class CustomerServiceTest {
@Test
public void testHandleProduct() {
Product mockProd = Mockito.mock(Product.class);
// MissingMethodInvocationException
when(ProductManager.getProduct("apple")).thenReturn(mockProd);
...
}
}
然而,当我进行测试时,我从Mockito获得MissingMethodInvocationException
:
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.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
它抱怨我在when()
内部没有调用方法,但是我在ProductManager.getProduct("apple")
中调用了公共静态方法when(...)
,为什么Mockito会提升这个对我有误?我不明白。
答案 0 :(得分:1)
Mockito无法模拟静态方法。使它成为一个实例方法,您的代码将起作用。
还有其他框架可以允许(例如Powermock),但这是一种相当糟糕的做法,也是设计糟糕的表现。您应该创建一个实例并执行依赖注入。如果一个方法非常小,可以在测试其他类时间接测试(例如Math.max()
),那么就不需要进行模拟。
在您发布的代码中,您有getProduct()
,但在堆栈跟踪中它是getArticles()
- 我假设代码只是一个简化的示例,而堆栈跟踪是实际的。
以下是一些解释测试/模拟静态方法问题的文章: