在Junit测试中使用JMockit多次模拟静态方法

6

我有一个包含静态方法的类,我正在使用JMockit进行模拟。假设它看起来像这样:

public class Foo {
    public static FooValue getValue(Object something) {
        ...
    }
    public static enum FooValue { X, Y, Z, ...; }
}

我有另一个类(我们称之为MyClass),它调用Foo的静态方法; 我正在为这个类编写测试用例。我的JUnit测试使用JMockit,看起来像这样:

public class MyClassTest extends TestCase {
    @NonStrict private final Foo mock = null;

    @Test public void testMyClass() {
        new Expectations() {
            {
                Foo.getValue((Object) any); result = Foo.FooValue.X;
            }
        };
    }

    myClass.doSomething();
}

这段代码运行良好,当执行测试时,MyClass实例将正确地获取Foo.getValue()枚举值为Foo.FooValue.X。
现在,我想遍历枚举中的所有值,并重复运行测试。如果我将上面的测试代码放在for循环中,并尝试将模拟静态方法的结果设置为每个枚举值,那么这样做是不起作用的。Foo.getValue()的模拟版本总是返回Foo.FooValue.X,而不是我通过枚举迭代器遍历枚举时的任何其他值。
我该如何在单个JUnit测试内多次模拟静态方法?我想做类似于这样的操作(但显然这样做是无效的)。
public class MyClassTest extends TestCase {
    @NonStrict private final Foo mock = null;

    @Test public void testMyClass() {

        for (final Foo.FooValue val : Foo.FooValue.values() {

            new Expectations() {
                {
                    // Here, I'm attempting to redefine the mocked method during each iteration
                    // of the loop. Apparently, that doesn't work.
                    Foo.getValue((Object) any); result = val;
                }
            };

            myClass.doSomething();
        }

    }
}

有什么想法吗?

你确定你的期望在除了FooValue.X之外的其他值上也能正确工作吗? - c_maker
1个回答

5

不要多次模拟方法,你应该在一次记录中记录多个连续的返回值:

public class MyClassTest extends TestCase
{
    @Test
    public void testMyClass(@Mocked Foo anyFoo)
    {
        new Expectations() {{
            Foo.getValue(any);
            result = Foo.FooValue.values();
        }};

        for (Foo.FooValue val : Foo.FooValue.values() {
            myClass.doSomething();
        }
    }
}

如果需要更多的灵活性,也可以使用 Delegate 来完成此操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接