@InjectMocks后为空

2022-09-03 04:24:34

我在使用JUnit进行单元测试时遇到一些传递依赖项的麻烦。

请考虑以下代码段:

这是我想要测试的类的依赖注入,让我们称之为控制器。

@Inject private FastPowering fastPowering;  

这是单元测试:

@RunWith(MockitoJUnitRunner.class)
public class ControllerTest {

@Mock
FastPowering fastPower;

@InjectMocks
Controller controller;

@Test
public void test() {
    assertEquals(
            (controller.computeAnswer(new BigDecimal(2), 2)).longValue(),
            (long) Math.pow(2, 2));
    }
}

似乎fastPower是空的,请解释如何解决这个问题。空指针异常,因为调用@injected字段(fastPower)在.computeAnswer方法中)

编辑:

解决了我应该阅读有关@Mock和@Spy之间的区别...

由于很多评论,我正在为解决方案添加更多的上下文

不同之处在于,在模拟中,您正在创建一个完整的模拟或假对象,而在间谍中,有真实对象,您只是监视或存根它的特定方法。当然,在间谍对象中,由于它是一个真正的方法,因此当您不存根该方法时,它将调用真正的方法行为。

如果 fastPower 被注释为@Mock它的方法都是虚拟的,但 controller.computeAnswer 依赖于它们来计算。一个人必须提供行为。

如果使用间谍而不进行存根,那么正在执行fastPower的真正实现,最终返回所需的值。

另一种选择是使用真正的 FastPowering 实例

https://github.com/mockito/mockito/wiki/Using 间谍(和假货)https://github.com/mockito/mockito/wiki/Mocking-Object-Creation

一些堆栈溢出线程概述了模拟框架中的模拟与间谍之间的区别

简答:替换为,并且应该工作正常@Mock@Spy


答案 1

用于启动 和 对象。您的测试将如下所示:MockitoAnnotations.initMocks@Mock@InjectMocks

@Mock
FastPowering fastPower;

@InjectMocks
Controller controller;

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

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

答案 2

我通过删除我在@Before方法中创建的无关的新实例来解决此问题(请参阅下面的示例)。它也在初始化后通过移动来修复,但是由于Mockito无论如何都创建了,因此该解决方案较差。MockitoAnnotations.initMocks(this)myClassmyClass

// Note - you may need @mock(name="foo") to help mockito differentiate props
//        if they have the same type
@mock
private Thing something;

@InjectMocks
private MyClass myClass;

@Before
 public void setUp() {
    MockitoAnnotations.initMocks(this); // Moving this below the next line fixed it...
    myClass = new MyClass() // But just remove this line and let Mockito do the work
}