Willy willy
Willy willy

Reputation: 31

Unit testing a value passed to a static method

Example code:

class MyClass {
    public void myMethod(Request request) {
        Item item = getItem();
        ItemUtilHelper.setCertainProperties(newProperty, item);
        differentClass.staticMethod(item);
    }
}

The ItemUtilHelper already has a unit test class to verify item gets properly updated.

How would I go about unit testing that differentClass.staticMethod gets called with an updated item parameter?

Upvotes: 3

Views: 1738

Answers (3)

Turing85
Turing85

Reputation: 20205

Let me start by saying that the static method in and of itself is a code smell. Miško Hevery summed up it quite nicely by saying:

The basic issue with static methods is they are procedural code. I have no idea how to unit-test procedural code. Unit-testing assumes that I can instantiate a piece of my application in isolation.


If you want to use Mockito only, your problem is not solvable:

What are the limitations of Mockito

Mockito 2.x specific limitations

  • ...

  • Cannot mock static methods

  • ...

(See Mockito FAQ)


You can use PowerMock to achieve your goal. But be warned: PowerMock operates on bytecode level. This means that

  • you may not be testing exactly the same bytecode you use in production (say hello to Heisenbugs) and
  • this can screw with other tools, e.g. JaCoCo

If you still want to proceed, then what you are looking for is a Spy. You can find a tutorial on PowerMock's wiki. While not directly related, the answers to this question give some additional examples on how to create a spy of a class. A throughout example can be found on Automation Rhapsody.

Upvotes: 4

Rea Sand
Rea Sand

Reputation: 173

Seeing how much pain you are having testing this side-effectful operation, have you considered applying the functional paradigm?

Static methods aren't smells. Quite the opposite infact. Methods with side effects, as indicated by the void keyword, are what's smelly about that code snippet. Those kinds of methods generally are really hard to test and understand (as you noticed I suppose). When dealing with effects, consider returning meaningful values (like maybe a Try or a Future depending on what your method does; have a look at vavr) instead. That is, exchange the side effect with a data structure that deals with it in a functional way (the keyword here is effectful programming in the context of functional programming). And don't mutate state (your Item) in place. Rather use immutable data structures and return a new instance with updated values (you can use lenses for this).

What you end up with is a bunch of functions for which the values they return depend only on their argument. This feature is called referential transparency: you can replace every call of that function by its value, no matter the computational context. A function exhibiting this feature is called pure. That value you can then easily define assertions against in your unit test without passing any mocks.

Upvotes: 1

Anatolii
Anatolii

Reputation: 14680

In addition to what @Turing85 said it's better to refactor static methods into public non-static ones. Then, an object possessing such methods can be passed into a method or constructor as a parameter and thus easily mocked or spied on. By doing so, you easily test your method logic and don't worry about object dependencies which functionality you don't want to test at the moment.

Upvotes: 1

Related Questions