简体   繁体   中英

Strange behaviour while Testing using Mockito and JUnit

here i am testing a method from TestedClass with signature:

public static boolean getBoolean(ClassA classA);

Here is my mock object configuration.

@Mock
private ClassA mockedCLass;  //I try to mock ClassA behaviour

.....

when(mockedClass.getValues()).thenReturn(null,emptyList,oneElementList,defaultList);

getBoolean() methods uses mocked object. Unfortunately it seems that mock is behaving completely wrong when i use this approach.

boolean res1 = TestedClass.getBoolean(mockedClass);
boolean res2 = TestedClass.getBoolean(mockedClass);
boolean res3 = TestedClass.getBoolean(mockedClass);
boolean res4 = TestedClass.getBoolean(mockedClass);

However when I split things like that:

when(mockedClass.getValues()).thenReturn(null);
boolean res1 = TestedClass.getBoolean(mockedClass);

when(mockedClass.getValues()).thenReturn(emptyList);
boolean res2 = TestedClass.getBoolean(mockedClass);

and so on, everything is fine. What is happening here? I would be grateful for any help.

EDIT: //Test Cases

List<String> emptyList = Collections.<String>emptyList();
List<String> defaultList = Arrays.asList("one", "two", "three");
List<String> oneElementList = Arrays.asList("one");

Here is boolean method example from TestedClass.

 public static boolean getBoolean(ClassA classA){
 return classA.getValues() == null || classA.getValues().size() <= 1; }

When i am invoking test cases for first approach i am getting:

1)null,defaultList,oneElementList -> true,true,true instead of true,false,true
2)oneElementList,null,defaultList -> error, Null pointer exception
3)null,oneElementList,defaultList,emptyList -> true,false,true,true instead of true,true,false,true
4)null or defaultList or oneElementList or emptyList -> works fine for one case

In your getBoolean method

public static boolean getBoolean(ClassA classA) {
    return classA.getValues() == null || classA.getValues().size() <= 1;
}

you're invoking your stubbed method twice. Each call consumes one value from those provided to thenReturn , until the last value, which is then repeated.

You'll probably want to extract the result of getValues once and reuse it.

public static boolean getBoolean(ClassA classA) {
    List<String> values = classA.getValues();
    return values == null || values.size() <= 1;
}

As Rogério has suggested in the comments, it's better practice to restrict your tests to distinct scenarios, ie. one per input value. This is similar to what occurs in your second approach. Each test would generate its own stub for the invocation to getValues that would not interfere with the others.

You'd have one test for a null argument, one for an empty list, one for a list with one element, and one with more than one element. For example

@Test
public void nullArgument() {
    when(mockedClass.getValues()).thenReturn(null);
    Assert.assertTrue(TestedClass.getBoolean(mockedClass));
}
@Test
public void emptyListArgument() {
    List<String> emptyList = Collections.<String>emptyList();
    when(mockedClass.getValues()).thenReturn(emptyList);
    Assert.assertTrue(TestedClass.getBoolean(mockedClass));
}

and so on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM