有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaJMockit:如何根据构造函数中给定的参数模拟方法?

我想使用JMockit模拟以下类:

public class A {

    private int n;

    public A(int n) {
        this.n = n;
    }

    public boolean isCorrect() {
        return n % 2 == 0;
    }
}

这个类在我的代码中都是初始化的,在我的测试中,我通常无法访问代码的这一部分
在我的一些测试中,我想模拟它,这样如果用值3初始化该类,“isCorrect”将返回true(这不是正常行为),而在其他一些测试中,我想模拟它,这样“isCorrect”将返回false,无论它是如何初始化的

我试图在文档中找到一种方法来实现它,但它不是那么友好,我放弃了


共 (2) 个答案

  1. # 1 楼答案

    对于第一个案例,您可以:

    new MockUp<A> () {
         private int n;
         @Mock public void $init(int n) { this.n = n; }
         @Mock public boolean isCorrect() { return n == 3; }
    };
    

    第二个例子是:

    new MockUp<A> () {
         @Mock public boolean isCorrect() { return false; }
    };
    

    例如,这会打印false,true,false,false:

    new MockUp<A> () {
         private int n;
         @Mock public void $init(int n) { this.n = n; }
         @Mock public boolean isCorrect() { return n == 3; }
    };
    System.out.println(new A(2).isCorrect());
    System.out.println(new A(3).isCorrect());
    
    new MockUp<A> () {
         @Mock public boolean isCorrect() { return false; }
    };
    System.out.println(new A(2).isCorrect());
    System.out.println(new A(3).isCorrect());
    

    编辑

    在您的评论之后,仅针对特定的n值模拟类的一种方法是使用反射来检查字段的值:

    new MockUp<A> () {
         @Mock public boolean isCorrect(Invocation invocation) {
            // Gets the invoked instance.
            A a = invocation.getInvokedInstance();
            int n = Deencapsulation.getField(a, "n");
            if (n == 3) return true;
            else return a.isCorrect();
         }
    };
    

    但它变得有点脆弱,因为它取决于类a中变量的名称

    一个可能更好的替代方法是在类A中为测试目的提供一个包保护的getter:int getN() { return n; },并且您不再需要反射

  2. # 2 楼答案

    谢谢@assylias的回答。我想我找到了一个更好的方法来实现第一个模拟,它结合了第一个和第二个(编辑后)答案中的想法。事情是这样的:

    new MockUp<A> () {
    
        private int n;
    
        @Mock
        public void $init(Invocation inv, int n) {
            this.n = n;
            inv.proceed();
        }
    
        @Mock
        public boolean isCorrect(Invocation inv) {
            if (n == 3) {
                return true;
            }
            return inv.proceed();
        }
    };
    

    更新

    对于第二个模拟(野蛮的假返回),可以这样做:

    new MockUp<A> () {
    
        @Mock
        public boolean isCorrect() {
            return false;
        }
    };
    

    再次感谢@assylias帮我做到这一点:)