进行单元测试时,来自Mockito的MissingMethodInvocationException



我有一个类,它包含公共静态方法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);
   }
}

我在CustomerService类中对handleProduct()方法进行了单元测试。我使用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()内部我不调用方法,但我在when(...)中调用了公共静态方法ProductManager.getProduct("apple"),为什么Mockito向我提出这个错误?我不明白。

Mockito不能模拟静态方法。将它作为一个实例方法,您的代码就可以工作了。

还有其他框架允许这样做(例如Powermock),但这是一种相当糟糕的做法,也是糟糕设计的标志。您应该创建一个实例并进行依赖项注入。如果一个方法很小,可以在测试其他类(例如Math.max())的同时进行间接测试,那么就没有必要进行嘲讽。

在您发布的代码中,您有getProduct(),但在堆栈跟踪中是getArticles()——我认为该代码只是一个简化的示例,而堆栈跟踪是实际的。

以下几篇文章解释了测试/模拟静态方法的问题:

  • https://softwareengineering.stackexchange.com/questions/231594/mocking-static-methods
  • http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
  • http://blog.christianposta.com/testing/java-static-methods-can-be-a-code-smell/
  • 为什么Mockito不模拟静态方法

相关内容

  • 没有找到相关文章

最新更新