java - EasyMock:如何在集合顺序无关紧要的情况下验证值集合的方法顺序

标签 java junit mocking easymock

我有一个测试,其中我有一组特定值,两种不同的方法将针对该组中的每个值执行一次。我需要检查这两种方法是否以相对于彼此的特定顺序调用,但与值集的顺序无关。例如:

String[] values = { "A", "B", "C" };

for (...<loop over values...) {
    methodOne(value);
    methodTwo(value);
}

values 的顺序无关紧要,但我需要验证是否调用了 methodOne()methodTwo()集合中的每个值以及 methodOne() 总是在 methodTwo() 之前调用。

我知道我可以创建一个控件并为每个值期望 methodOne()methodTwo(),然后执行 control.verify(),但这取决于 values 的特定顺序。

有没有一种优雅的方式来做到这一点?

谢谢

最佳答案

您可以使用 andAnswer() 来做到这一点。

基本上,在 methodOne()andAnswer() 中,您设置了一些变量来保存传入的 value 是什么。

然后在 methodTwo()andAnswer() 中,您断言相同的参数与您从 methodOne 答案中保存的内容匹配。

因为每次调用 methodOne 都会修改这个变量,所以会确保 methodTwo() 总是在 methodOne() 之后调用。

注意这个解决方案不是线程安全的

首先,您需要一些东西来保存 methodOne 调用中的变量。这可以是具有单个字段的简单类,甚至可以是一个元素的数组。您需要这个包装器对象,因为您需要在 IAnswer 中引用它,而 IAnswer 需要一个 final 或有效的 final 字段。

private class CurrentValue{
    private String methodOneArg;

}

现在您的期望。在这里我调用了你正在测试的类(The System Under Test)sut:

    String[] values = new String[]{"A", "B", "C"};

    final CurrentValue currentValue = new CurrentValue();

    sut.methodOne(isA(String.class));

    expectLastCall().andAnswer(new IAnswer<Void>() {

        @Override
        public Void answer() throws Throwable {
            //save the parameter passed in to our holder object
            currentValue.methodOneArg =(String) EasyMock.getCurrentArguments()[0];
            return null;
        }

    }).times(values.length); // do this once for every element in values

    sut.methodTwo(isA(String.class));
    expectLastCall().andAnswer(new IAnswer<Void>() {

        @Override
        public Void answer() throws Throwable {
            String value =(String) EasyMock.getCurrentArguments()[0];
            //check to make sure the parameter matches the 
            //the most recent call to methodOne()

            assertEquals(currentValue.methodOneArg, value);
            return null;
        }

    }).times(values.length); // do this once for every element in values

    replay(sut);
    ... //do your test
    verify(sut);

编辑

您是正确的,如果您使用的是 EasyMock 2.4 +,则可以使用新的 Capture 类以更简洁的方式为 methodOne() 获取参数值。但是,您可能仍需要为 methodTwo() 使用 andAnswer() 以确保按顺序调用正确的值。

这是使用 Capture 的相同代码

Capture<String> captureArg = new Capture<>();

    sut.methodOne(and(capture(captureArg), isA(String.class)));
    expectLastCall().times(values.length);

    sut.methodTwo(isA(String.class));
    expectLastCall().andAnswer(new IAnswer<Void>() {

        @Override
        public Void answer() throws Throwable {
            String value =(String) EasyMock.getCurrentArguments()[0];
            assertEquals(captureArg.getValue(), value);
            return null;
        }

    }).times(values.length);

    replay(sut);

关于java - EasyMock:如何在集合顺序无关紧要的情况下验证值集合的方法顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29176953/

相关文章:

JavaFX:CSS 文件中的未知属性

c# - 使用计算机作为USB通信中间人

Java NIO isConnectable 始终返回 true

java - ScheduledThreadPoolExecutor 线程安全

java - 如何使用 JUnit 模拟此 webClient?

java - 使用 Mockito 从模拟中抛出已检查的异常

java - 如何在略有不同的 jar 列表上运行测试用例?

java - Apache Camel JUnit 测试警告

c# - 如何在 .NET 测试中传入模拟的 HttpClient?

android - 如何在抛出的异常中模拟 Crashlytics 静态方法