google / gwtmockito

Better GWT unit testing
https://google.github.io/gwtmockito
Apache License 2.0
157 stars 51 forks source link

How to mock static methods? #59

Closed Bargath closed 8 years ago

Bargath commented 8 years ago

I have a class like this:

public class Utilities{ public static int getValue(){ return 10; } }

I want to write test for this class:

public class ServiceClass{ public void populate(){ if(Utilities.getValue() < 15){

} } }

Is it possible to mock what Utilities.getValue() return?

ekuefler commented 8 years ago

Unfortunately not. Static methods are a classic barrier to unit testing since they don't give you the opportunity to substitute your own mock object to replace the method. This blog post describes the problem in more detail: http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/

The traditional solution is to use dependency injection. This would involve giving your Utilities class a constructor and making its methods non-static, and passing a Utilities instance into your Service class. Then in tests for the Service class, you can pass in a mock Utilities. GWT and GwtMockito even make this a little easier since you can use GWT.create to create the service class instead of passing it in your constructor, and GwtMockito will cause that to return a mock in tests. If Utilities is owned by someone else and you can't change it directly to be nonstatic, you would have to make something like a UtilitiesWrapper class with non-static methods that delegate to the static methods in Utilities (most of my GWT projects end up doing this for things like Window and Window.Location that GWT only makes available as static classes).

As a method of last resort, you could look into alternative mocking frameworks like PowerMock, which does a lot of black magic to give you a way to mock static methods. This tends to be fairly dangerous and brittle though, so if at all possible you're better off structuring your code using dependency injection to improve its testability.

schnatterer commented 8 years ago

Isn't this a duplicate of #41?