Mockito:如何在 Spy 中模拟对象

Mockito: How to Mock objects in a Spy

应用程序在JEE 环境中运行。 我希望将 Spy 注入到被测 bean 中。 Spy 对象内部也有一些应该注入的 bean。如何将这些 bean 的模拟注入 Spy?

这是用例:

package testinject2;

import javax.inject.Inject;

public class ABean {

    @Inject
    BBean b;
    
    public void print() {
        System.out.println("Hi, I'm ABean");
        b.print();
    }
}
package testinject2;

import javax.inject.Inject;

public class BBean {

    @Inject
    CBean c;
    
    public void print() {
        System.out.println("Hi, I'm BBean");
        c.print();
    }
}
package testinject2;

public class CBean {

    public void print() {
        System.out.println("Hi, I'm CBean");
    }
}
package testinject2;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)

public class ABeanTest {

    @Spy
    CBean c = new CBean();
    
    @Spy
    BBean b = new BBean();
    
    @InjectMocks
    ABean beanUnderTest;
    
    @Test
    public void test() {
        beanUnderTest.print();
    }
}

我希望获得

Hi, I'm ABean
Hi, I'm BBean
Hi, I'm CBean

但是我有一个 null ponter 异常,因为 CBean 没有注入 BBean。

将 Spy 对象注入另一个 Spy 的正确方法是什么?

您需要通过 @InjectMocks 注释定义应注入哪些对象模拟,但它不能与 @Spy 注释一起使用。参见 mockito issue
最简单的解决方案是使用 Mockito.spy 而不是 @Spy@InjectMocks:

    @InjectMocks
    BBean b = Mockito.spy(new BBean());

完整测试代码:

@RunWith(MockitoJUnitRunner.class)
public class ConfigTestObject {

    @Spy
    CBean c = new CBean();

    @InjectMocks
    BBean b = Mockito.spy(new BBean());

    @InjectMocks
    ABean beanUnderTest;

    @Test
    public void test() {
        beanUnderTest.print();
    
        //verify that mocks is working
        verify(c, atLeast(1)).print();
        verify(b, atLeast(1)).print();
    }
}