将模拟对象注入要在测试中声明为测试的字段的测试对象使用Mockito不起作用?

时间:2013-10-25 02:37:42

标签: java mockito

我有一个班级,我正在为我的服务注入代理。

Service service
{
    private ServiceProxy proxy;
    public Service(ServiceProxy proxy)
    {
        this.proxy = proxy; 
    }
}

对它的测试是:

ServiceTest
{
    @Mock
    ServiceProxy mockProxy;
    Service service = new Service(mockProxy);
}

如果我像这样初始化我的类,当我想使用服务对象时,我总是得到NPE。为什么Mockito会这样做?有什么方法可以解决这个问题,而不是在每次测试中声明它?

2 个答案:

答案 0 :(得分:6)

如果您使用的是Mockito 1.9.0或更高版本,那么实现您想要的最佳方式就是:

@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {

    @Mock
    private ServiceProxy proxy;

    @InjectMocks
    private Service service;

    @Test
    public void test() {
        assertNotNull(service);
        assertNotNull(proxy);
    }
}

首先是@RunWith(MockitoJUnitRunner.class)声明会导致@Mock和@InjectMocks注释在没有任何显式初始化的情况下自动工作。第二件事是从Mockito 1.9.0开始@InjectMocks注释可以使用构造函数注入机制,这是 Service 类的最佳选择。

@InjectMocks的其他选项是 Setter injection Field injection (参见docs BTW),但是你需要一个无参数构造函数来使用它们。

总结 - 您的代码无法正常工作,因为:

  • 你没有使用MockitoJUnitRunner和MockitoAnnotations.initMocks(这个)所以@Mock注释不起作用
  • 即使上述内容得到满意,您的示例也会失败,因为 mockProxy 会在构建测试并且您的服务被尝试之后初始化在测试类构造期间初始化,因此它接收null mockProxy 引用。

如果由于某种原因您不想使用@InjectMocks,唯一的方法是在测试方法体内或@Before带注释的setUp方法中构建 Service 对象。

答案 1 :(得分:2)

将您的测试类编写为此,它将使用模拟Service初始化ServiceProxy

class ServiceTest
{
@Mock
ServiceProxy mockProxy;

//This will inject the "ServiceProxy" mock into your "Service" instance.
@InjectMocks
Service service = new Service(mockProxy);

@Before
public void init() {
//This will initialize the annotated mocks 
MockitoAnnotations.initMocks(this);
}

@Test
public void test() {
... 
}
}