user842225
user842225

Reputation: 6009

MissingMethodInvocationException from Mockito when do unit test

I have a class which contains an public static method getProduct(String name):

public class ProductManager {
  public static Product getProduct(String name) {
        Product prod = findProduct(name);
        return prod;
  }
}

Another CustomerService class use the above ProductManager:

public class CustomerService {
   ...
   public void handleProduct() {
     Product appleProd = ProductManager.getProduct("apple");
     doHandle(appleProd);
   }
}

I unit test handleProduct() method in CustomerService class. I use mockito to mock the ProductManager.getProduct("apple") part in test:

public class CustomerServiceTest {
  @Test
  public void testHandleProduct() {
    Product mockProd = Mockito.mock(Product.class);

    // MissingMethodInvocationException
    when(ProductManager.getProduct("apple")).thenReturn(mockProd);
    ...
  }
}

However, when I run my test, I got MissingMethodInvocationException from Mockito:

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.

It complains that inside when() I don't call method, but I do call the public static method ProductManager.getProduct("apple") in when(...), why Mockito rise this error to me ? I don't understand.

Upvotes: 0

Views: 579

Answers (1)

Jaroslaw Pawlak
Jaroslaw Pawlak

Reputation: 5588

Mockito cannot mock static methods. Make it an instance method and your code will work.

There are other frameworks that allow that (e.g. Powermock), however this is rather bad practice and a sign of bad design. You should create an instance and do dependency injection. If a method is so small that it can be tested indirectly while testing other class (e.g. Math.max()), than there is no need for mocking.

In the code you posted you have getProduct(), but in the stack trace it is getArticles() - I assume that the code was just a simplified example, while the stack trace is actual.

Here are a few articles explaining the problem of testing/mocking static methods:

Upvotes: 1

Related Questions