【问题标题】:JMockit mock private method in @PostConstruct@PostConstruct 中的 JMockit 模拟私有方法
【发布时间】:2016-05-22 00:55:43
【问题描述】:

上下文

在我的测试类中有一个 @PostConstruct 带注释的方法,它调用另一个私有方法。

@PostConstruct
public void init() {
    longWork(); // private method
}

JMockit 的默认行为是在注入时执行 @Tested 类的 @PostConstruct 方法。

如果@Tested 类有一个方法用 javax.annotations.PostConstruct,它应该在之后执行 注射。

https://github.com/jmockit/jmockit1/issues/13

问题

JMockit 调用了init() 方法,这是我不想要的。

来自线程转储:

at com.me.Worker.longWork(Worker.java:56)
at com.me.Worker.longWork.init(Worker.java:47)
...
at mockit.internal.util.MethodReflection.invoke(MethodReflection.java:96)

如何模拟/删除/阻止该调用?

尝试

我尝试模拟initlongWork 方法,如下所示。但是,这会导致 NullPointerException 因为 sut 尚未注入。

@Before
public void recordExpectationsForPostConstruct()
{
    new NonStrictExpectations(sut) {{ invoke(sut, "init"); }};
}

【问题讨论】:

    标签: java unit-testing jakarta-ee junit jmockit


    【解决方案1】:

    您可以尝试在不使用@Tested 的情况下手动初始化要测试的类。然后,通过 setter 方法(或使用 mockit.Deencapsulation.setField() 方法)设置模拟依赖项。

    您可以尝试类似的方法;

    //Define your class under test without any annotation
    private MyServiceImpl serviceToBeTested;
    
    //Create mock dependencies here using @Mocked like below
    @Mocked Dependency mockInstance;
    
    
    
    @Before
    public void setup() {
        //Initialize your class under test here (or you can do it while declaring it also). 
        serviceToBeTested = new MyServiceImpl();
    
        //Set dependencies via setter (or using mockit.Deencapsulation.setField() method)
        serviceToBeTested.setMyDependency(mockInstance);
    
        //Optionally add your expectations on mock instances which are common for all tests
        new Expectations() {{
            mockInstance.getName(); result = "Test Name";
            ...
        }};
    }
    
    @Test
    public void testMyMethod(@Mocked AnotherDependency anotherMock) {
        //Add your expectations on mock instances specifics to this test method.
        new Expectations() {{
            mockInstance.getStatus(); result = "OK";
            anotherMock.longWork(); result = true;
            ...
        }};
    
        //Set dependencies via setter or using mockit.Deencapsulation.setField() method
        Deencapsulation.setField(serviceToBeTested, "myAnotherDep", anotherMock);
    
        //Invoke the desired method to be tested
        serviceToBeTested.myMethod();
    
        //Do the verifications & assertions
        new Verifications() {{
          ....
          ....
    
        }};
    
    }
    

    【讨论】:

    • 你能举个例子吗?
    【解决方案2】:

    也许您可以将 longWork 方法委托给不同的类并模拟这个类。编写测试的困难通常是设计缺陷的标志

    【讨论】:

    • 我同意这是一种可能性。但是我不同意 init 方法中发生的所有事情都应该委托给其他类。因此,我正在寻找一种模拟 init 方法的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多