【问题标题】:Using JMockit, how do I mock an interface method for specific input parameter values?使用 JMockit,我如何模拟特定输入参数值的接口方法?
【发布时间】:2026-02-21 22:35:01
【问题描述】:

假设我有一个接口Foo 和方法bar(String s)。我唯一想嘲笑的是bar("test");

我不能使用静态部分模拟来做到这一点,因为我只希望在传递“测试”参数时模拟 bar 方法。我不能通过动态部分模拟来做到这一点,因为这是一个接口,我也不希望模拟实现构造函数。我也不能对MockUp 使用接口模拟,因为我无法注入模拟实例,它是在代码中的某处创建的。

我有什么遗漏吗?

【问题讨论】:

  • Foo是如何创建的?示例代码会很好。
  • 有什么我不明白的地方吗?为什么Foo foo = mock(FooImpl.class); when(foo.bar("test")).thenReturn("mocked"); when(foo.bar(anyString())).thenCallRealMethod() 不适合你。编辑:一开始我没有看到你在使用 JMockit。

标签: java unit-testing junit jmockit


【解决方案1】:
final Foo foo = new MockUp<Foo>() {
        @Mock
        public bar(String s)(){
        return "test";
        }
    }.getMockInstance();
foo.bar("") will now retun "test"...

【讨论】:

    【解决方案2】:

    确实,对于这种情况,您需要动态模拟实现所需接口的类。但是 JMockit 目前不支持这种组合(@Capturing + 动态模拟)。

    也就是说,如果实现类是已知的并且可用于测试代码,那么它可以单独使用动态模拟来完成,如下面的示例测试所示:

    public interface Foo {
        int getValue();
        String bar(String s);
    }
    
    static final class FooImpl implements Foo {
        private final int value;
        FooImpl(int value) { this.value = value; }
        public int getValue() { return value; }
        public String bar(String s) { return s; }
    }
    
    @Test
    public void dynamicallyMockingAllInstancesOfAClass()
    {
        final Foo exampleOfFoo = new FooImpl(0);
    
        new NonStrictExpectations(FooImpl.class) {{
            exampleOfFoo.bar("test"); result = "aBcc";
        }};
    
        Foo newFoo = new FooImpl(123);
        assertEquals(123, newFoo.getValue());
        assertEquals("aBcc", newFoo.bar("test")); // mocked
        assertEquals("real one", newFoo.bar("real one")); // not mocked
    }
    

    【讨论】:

    • 我能够通过 MockUp + if-else 检查输入参数来实现它。无论如何,谢谢你的回复!如果对 exampleOfFoo.bar("not_test") 的调用将在堆栈中以 exampleOfFoo.bar("test") 结束,该解决方案将如何表现?会调用模拟方法还是原始方法?
    • 将返回记录的结果"aBcc"。 (至少如果使用最新版本的 JMockit。)