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

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

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


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

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

有没有一种优雅的方法可以做到这一点?

谢谢

最佳答案

您可以使用andAnswer()执行此操作。

基本上,在andAnswer()methodOne()内部,设置一些变量以保存传入的value是什么。

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

由于每次调用methodOne都会修改此变量,因此可以确保在methodOne()之后始终调用methodTwo()。

请注意,此解决方案不是线程安全的

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

private class CurrentValue{
    private String methodOneArg;

}


现在您的期望。在这里,我调用了您正在测试的类(被测系统)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()的参数值。但是,您可能仍需要对andAnswer()使用methodTwo()来确保依次调用正确的值。

这是使用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/

10-16 01:47