【问题标题】:Strange behaviour while Testing using Mockito and JUnit使用 Mockito 和 JUnit 进行测试时的奇怪行为
【发布时间】:2016-06-22 14:18:49
【问题描述】:

我在这里测试一个带有签名的 TestedClass 方法:

public static boolean getBoolean(ClassA classA);

这是我的模拟对象配置。

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

.....

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

getBoolean() 方法使用模拟对象。不幸的是,当我使用这种方法时,mock 的行为似乎完全错误。

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

但是,当我这样拆分时:

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

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

等等,一切都很好。这里发生了什么?如果有任何帮助,我将不胜感激。

编辑: //测试用例

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

这是来自TestedClass.的布尔方法示例

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

当我为第一种方法调用测试用例时,我得到:

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

【问题讨论】:

    标签: java unit-testing junit mocking mockito


    【解决方案1】:

    在您的getBoolean 方法中

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

    你调用了你的存根方法两次。每次调用都会使用提供给thenReturn 的值中的一个值,直到最后一个值,然后重复。

    您可能希望提取一次 getValues 的结果并重复使用它。

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

    正如Rogério 在 cmets 中所建议的那样,最好将测试限制在不同的场景中,即。每个输入值一个。这类似于您的第二种方法中发生的情况。每个测试都会为调用getValues 生成自己的存根,不会干扰其他测试。

    您将对null 参数进行一项测试,一项针对空列表的测试,一项针对包含一个元素的列表,一项针对包含多个元素的测试。例如

    @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));
    }
    

    等等。

    【讨论】:

    • 正确,但不是一个好的答案。真正的问题是 OP 试图在一个测试方法中编写三个不同的测试(自动化测试初学者相对常见的错误)。更好的答案是编写一个检查 true 返回 null 的测试,第二个检查 true 返回空列表的测试,第三个测试非空列表的情况;那么每个测试都会为模拟方法记录一个返回值。
    • @Rogério 你是对的。我已经扩展了我的答案以纳入您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多