Does it make sense to Unittest wrapper methods

3k views Asked by At

This question is somewhat philosophical. Given i have a Method like this:

public List<String> getStuffByName(@NotNull String name) throws SomeException {
        return someDependency.createQuery().byName(name).list().stream()
                .map(execution -> execution.getProcessInstanceId())
                .collect(Collectors.toList());
}

Basically all it does is call a dependencies method and then process it using the stream api.

A Unittest - in a strict understanding(?) - is only testing one isolated unit. So i would Mock the dependencies, as i assume they also are already tested units themselves.

If I go through with this, i end up with a Method that exclusively consists of stuff that is tested elsewhere.

Eg my JMockit Test would look like this:

public void test_get_processes_for_bkey_2(@Mocked ExecutionQuery query,
                                              @Mocked List<String> processes,
                                              @Mocked List<Execution> executions,
                                              @Mocked Stream<Execution> e_stream,
                                              @Mocked Stream<String> pid_stream,
                                              @Mocked Stream<String> pdef_stream

    ) {
    new Expectations() {
        {
            someDependency.createQuery(); result = query;
            query.byName("somefilter"); result = query;
            query.list(); result = executions;
            executions.stream(); result = e_stream;
            e_stream.map((Function) any); result = fin_stream;
            fin_stream.collect((Collector) any); result = processes;
            processes.size(); result = 2;
        }
    };

    assertEquals(tested.getStuffByName("somefilter").size(), 2);
}

But what does this test really tell me?

In test-driven-development, would i omit tests of such "wrapper" methods?

What would a professional approach to test this be, independent of Jmockit or other frameworks?

4

There are 4 answers

0
JB Nizet On

The contract of the method is to execute the query having the given name, and return the process instance IDs of the Execution instances returned by the query. Whether your method uses streams, or a for loop, or anything to do that is irrelevant.

So I would only stub the query and make it return a real list of 2 or 3 executions. Based on that list returned by the query, I would check that the returned List contains the appropriate 2 or 3 IDs, in the correct order.

0
Sergey Kalinichenko On

You do want to test all public methods, including ones that wrap logic from other methods. A passing unit test for this method tells you several important things:

  • The method getStuffByName exists,
  • The signature of getStuffByName is what you expect,
  • The logic of getStuffByName is pinned down by the checks in the unit test.

If someone decides to re-implement your getStuffByName method with loops instead of streams, because they wanted to back-port your code to an earlier version of Java, passing the unit test would let them know that their conversion worked correctly.

2
Markon On

The main idea behind unit tests is that they test 'units' of code, not the whole infrastructure or interaction between components. If you write a method like

public int sum(int a, int b){
  return a + b;
}

you are still using wrappers (int/Integer and the + method), but in that case you would write unit tests to check that your sum method works, wouldn't you? Because you might have done something like:

public int sum(int a, int b){
  return a;
}

and this is definitely a bug - but still, it's just a wrapper!

Okay, there are unit tests that know a bit more about the underlying system (white-box testing) and unit tests that know nothing about what is inside (black-box, no assumptions). So, it depends on you whether you want to test something or not - if you think your code is bug-free just because "it's just a wrapper", then we should stop writing tests, because everything can be thought as a wrapper.

0
Rogério On

A "professional approach" to test this would be to not mock anything. A good test should be as realistic as you can make it, while also keeping it sufficiently fast and stable.

Unit tests (in the pure/strict sense, where the unit is isolated from its dependencies through mocking) are overrated. This isn't just me saying it; authors like Kent Beck (the main "creator" of TDD) and Martin Fowler are no fans of "pure" unit testing either (see Is TDD Dead?, for example).

Mocking is best used in exceptional cases, where for practical reasons you just can't easily write the test without it. In my own experience, integration tests (with no or minimal mocking) have proved to be much better.