javaunit-testingjunitmockitoany

Is it recommended to use any() or a specific value for unit tests


I am curious about the best / recommended approach to follow when writing a unit test.

If I can easily create the specific values that would get passed for a function, should I create those in my unit tests and use them? Or can I use any() to mock for all values?

class Foo {
    bool func1(String abc, int xyz, Bar bar) {
        // ...
    } 
}

If I have a class like this that I want to mock for a specific behavior, which is a better approach?

@Mock
Foo mockFoo;
  1. Bar dummyBar = getTestBar();
    when(mockFoo.func1("value1", 1, dummyBar)).thenReturn(true);
    
  2. when(mockFoo.func1(anyString(), anyInt(), any())).thenReturn(true);
    

I am trying to identify when to use each. I feel using specific values will be better whenever possible and if it is simple to create those values. Use any() only when it is not easy to create such objects. i.e. Say I am refactoring a codebase and I see almost all unit tests are using any() even if I could use specific values. Will it be worth doing some cleanup on the code and make the unit tests use specific values?


Solution

  • For a function install(String id), any of the following are possible:

    It is entirely up to you: You'll need to pick which parameters matter to your test, and whether your test errs on the side of brittle (failing when it should pass) or permissive (passing when it should fail).


    As a side note, you can mix any combination of specific matchers like eq and general matchers like anyString, or you can use all real values that test equals just like eq; you just can't mix both styles in the same call.

    /* Any mix of matchers is OK, but you can't mix unwrapped values. Use eq() instead. */
    /*  bad: */ when(mockFoo.func1(   "example" , anyInt(), any())).thenReturn(true);
    /* good: */ when(mockFoo.func1(eq("example"), anyInt(), any())).thenReturn(true);
    
    /* Unwrapped values are OK as long as you use them for every parameter you pass. */
    /* good: */ when(mockFoo.func1(   "example" ,    0 ,    bar1 )).thenReturn(true);
    /* same: */ when(mockFoo.func1(eq("example"), eq(0), eq(bar1))).thenReturn(true);