Search code examples
javaunit-testingmockitojunit4

Should i mock List for stream operations?


I have a line of code in function which applies stream operations on an ArrayList as:

List<Entity> list = xyz(); 

long result = list.stream().map(n -> n.getData()).filter(n -> n == 1).count();

Now when i write a test for this method should i do like:

@Mock
private List<Entity> list;

//inside the test method
when(list.stream().map(any()).filter(any()).count()).thenReturn(someValue);

What is coming to my mind is that when we are calling stream operations in our code, we are basically going out of our class to call these functions. Since it is unit testing we should remain inside our module. Please clarify if i have some misconceptions. If we do not need to mock List, then why?


Solution

  • You could mock the list but it's probably way more trouble than it's worth. The list and stream interfaces are so large that it's difficult to mock them without either mocking every method (no thanks) or mocking only the methods that you use, which means you'd be relying on knowing internal implementation details of the method that you're testing. The latter leads to fragile tests. It's best to write a test that doesn't care about implementation details, just inputs and outputs.

    Mocking should be used when it's prohibitively hard to create a proper version of the object, or when you want to provide isolation for the test. Lists are not hard to create, and they are so well-tested that mocking them does not really provide any value for the increased isolation.

    Just create a list normally.

    list = Arrays.asList(new Entity(1), new Entity(2), new Entity(1));
    

    In this case, you would assert the result of the method to be 2.

    You may get some mileage out of mocking the Entity, however e.g.

    Mockito.when(Entity.getData()).thenReturn(1);