3

How do you guys create utils classes? Is there a standard way?

Like the headline says you can either have something like:

public class Utils {

   public static method1(){...}

   public static method2(){...}
...
}

and use it by calling Utils.method1(), but that way, when you write unit tests for the class that uses this utils class you cant mock the static methods so if they have a bug the unit test will fail.

Or, you can give an instance of the utils class in the constructor of the class using these utils and that way you can mock it in unit tests, but to me it looks very awkward giving an instance of a utils class to every class that uses it, and having to create an instance of a utils class in general. I mean something like if we have class A that uses a method from the Utils class we can do: A a = new A(new Utils());

Is there a way that achieves both? Or at least something that is standard in the industry? Or another way that I didnt think of?

tomer.z
  • 1,033
  • 1
  • 10
  • 25
  • What do you mean by the second method ("inject the utils class to the class thats using it in the constructor ... but it looks very awkward")? – Jonathan Lam Apr 21 '18 at 19:58
  • Edited, hope its clearer now – tomer.z Apr 21 '18 at 20:01
  • You can keep methods as static, but stub them using *statick mocking* using something like power mock in tests of code that uses the Utils class – ernest_k Apr 21 '18 at 20:01
  • https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html Apache StringUtils uses static methods, I guess they know what they are doing – Bentaye Apr 21 '18 at 20:01
  • @Bentaye Like I mentioned, this way has a flaw when unit testing which Im not sure they took into account when they wrote this utils class since they cant really... @ErnestKiwele I dont know a way to mock a static method, or a call to a static method, I mean how will you redirect the call `Utils.method1()` that your code makes to some other mock implementation? – tomer.z Apr 21 '18 at 20:07
  • @tomer.z you can test your static methods, as long as they are sufficiently simple. If you have to mock twenty classes to test your utility classes, then there is something wrong. Furthermore, there are frameworks that can mock static methods, e.g. PowerMock. But be warned: those frameworks perform bytecode manipulation and this can screw with e.g. JaCoCo/EclEmma. – Turing85 Apr 21 '18 at 20:09
  • If you really do not want to use static utility classes, you can use the [Singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern): create one single instance of your utility class, make it globally accessible through a static `instance()`-method of that utility class. – Turing85 Apr 21 '18 at 20:11
  • There are frameworks like `PowerMock` which allows mocking static methods, but usually, it is a bad idea and it means your code is designed badly. And as it was mentioned, they manipulate with bytecode. I would not recommend to use it. Otherwise, you should think if there is another way to design your code, so it won't be tightly-coupled with some dependencies and will be easy to test. You haven't provide the actual code, so I cannot say what actually could be changed in your case to achieve this. – ikos23 Apr 21 '18 at 20:18
  • @john tight coupling in and of itself is not the problem, as long as it occurs in the right places. If you, for example, write an annotation processor, you will need some references to e.g. the type system and the out console in mutliple classes. Providing them in a static utility class is in my opinion not a problem. The static class is your "interface" to the compile environment during annotation processing. – Turing85 Apr 21 '18 at 20:24
  • Thats an interesting though @john, I dont think the actual code really matters (its more of a conceptual design question, nothing specific). Basically what you are saying it that utils methods should be simple enough that they dont need to be tested? Because Im not sure I concur with your comment about bad design, sometimes you just have some small piece of logic that you use in a lot of places, for exmample calculating a square root in some math intensive program – tomer.z Apr 21 '18 at 20:25

3 Answers3

3

Utility classes should be part of the API and well tested. If you start thinking about dependency injection and mocking on that level, you already lost. Mocking should be done really carefully.

Alternatives:

  • default interface method implementations (since Java 8)
  • adapters decorating an instance of a class and providing the utility functions.
Florian Salihovic
  • 3,921
  • 2
  • 19
  • 26
2

Generally you may (and not have to) write static methods for utility methods that you don't need to mock or to switch to different implementation of them.
Some processing may require no mock or implementation switching. So make them static utility methods is acceptable.
Take for example a Math function such as computing the square root of a number. You should not need to mock it or to switch to another implementation.
So using a static method should not cause any issue.

For cases where you don't know if you need to mock/switch to other implementations, I think that you should favor instance methods as it is more flexible.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • Its not a question of knowing if you need to use a mock or not, I tried to describe a situation when you wrote some new classes and also a new utils class that these classes use, and like any new code the utils class needs to be tested so an assumption of it working when you write the unit tests for the classes that use it (which is what you have to assume when you call methods from that class in a static way) seemed a bit wrong to me – tomer.z Apr 21 '18 at 20:28
1

You can mock static methods in tests for classes that use your Utils class. Assuming you use JUnit, you can add a dependency on powermock:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.4</version>
</dependency>

Assuming a client class, such as:

class ClientCode {
    public void doSomething() {
        String value = Utils.method1();
    }
}

In the test for ClientCode, you can use powermock:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utils.class)
public class ClientCodeTest {

    @Test
    public void testDoSomething() {
        PowerMockito.mockStatic(Utils.class);
        BDDMockito.given(Utils.method1()).willReturn("<mock string value>");
    }
}
ernest_k
  • 44,416
  • 5
  • 53
  • 99