如何在Junit中使用@InjectMocks和@Autowired注释

时间:2015-12-03 13:58:53

标签: java spring junit mocking mockito

我有一个A类,它使用3个不同类和自动装配

public class A () {

    @Autowired
    private B b;

    @Autowired
    private C c;

    @Autowired
    private D d;
}

在对它们进行测试时,我希望只有2个类(B& C)作为模拟,并将D类自动装配为正常运行,此代码对我不起作用:

@RunWith(MockitoJUnitRunner.class)
public class aTest () {

    @InjectMocks
    private A a;

    @Mock
    private B b;

    @Mock
    private C c;

    @Autowired
    private D d;
}

甚至可以这样做吗?

3 个答案:

答案 0 :(得分:32)

应该是

@RunWith(SpringJUnit4ClassRunner.class)
public class aTest () {

    @Mock
    private B b;

    @Mock
    private C c;

    @Autowired
    @InjectMocks
    private A a;

}

如果您希望D成为Autowired,则无需在Test课程中执行任何操作。您的Autowired A应具有D的正确实例。 此外,我认为您需要使用SpringJUnit4ClassRunner Autowiring来正常工作,contextConfiguration设置正确。 由于您未使用MockitoJunitRunner,因此需要使用

自行初始化mocks
  

MockitoAnnotations.initMocks(java.lang.Object testClass)

答案 1 :(得分:5)

我遇到了同样的问题并尝试了Sajan Chandran的回答。它在我的情况下不起作用,因为我使用@SpringBootTest注释只加载我所有bean的一个子集。目标不是加载我正在嘲笑的bean,因为它们有很多其他依赖项和配置。

我发现以下解决方案的变体适用于我,在正常情况下也可以使用。

@RunWith(SpringRunner.class)
@SpringBootTest(classes={...classesRequired...})
public class aTest () {

    @Mock
    private B b;

    @Mock
    private C c;

    @Autowired
    @Spy
    private D d;

    @InjectMocks
    private A a;

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

}

答案 2 :(得分:0)

除了已接受的答案,如果您使用的是 spring-boot,使用 @MockBean 注释会更容易:

@RunWith(SpringRunner.class)
public class aTest () {

    @MockBean
    private B b;

    @MockBean
    private C c;

    @Autowired
    private A a;
}

如果您没有使用 spring-boot,@Autowired + @InjectMocks 的问题是 Spring 将首先加载 bean B 和 C 不需要的实例,然后它们被模拟替换。这是一种浪费,并且可能具有您不想要/无法加载的传递依赖项。始终建议为您的测试加载最小的 Spring 上下文。我会推荐这个:

@RunWith(SpringRunner.class)
@Import({A.class, D.class})
@ContextConfiguration(classes = aTest.class)
public class aTest () {

    @Bean
    private B b() {
        return Mockito.mock(B.class);
    }

    @Bean
    private C c() {
        return Mockito.mock(C.class);
    }

    @Autowired
    private A a;
}