如何在 Junit 中使用@InjectMocks 和@Autowired 注解
How to use @InjectMocks along with @Autowired annotation in Junit
我有一个 class A,它使用 3 个不同的 classes 和自动装配
public class A () {
@Autowired
private B b;
@Autowired
private C c;
@Autowired
private D d;
}
在测试它们时,我只想将 classes(B 和 C)中的 2 个作为模拟,并让 class D 正常自动装配 运行,此代码对我不起作用:
@RunWith(MockitoJUnitRunner.class)
public class aTest () {
@InjectMocks
private A a;
@Mock
private B b;
@Mock
private C c;
@Autowired
private D d;
}
甚至可以这样做吗?
应该是这样的
@RunWith(SpringJUnit4ClassRunner.class)
public class aTest () {
@Mock
private B b;
@Mock
private C c;
@Autowired
@InjectMocks
private A a;
}
如果您希望 D
成为 Autowired
,则无需在 Test
class 中执行任何操作。您的 Autowired
A
应该有正确的 D
实例。
此外,我认为您需要使用 SpringJUnit4ClassRunner
才能使 Autowiring
正常工作,并正确设置 contextConfiguration
。
因为您没有使用 MockitoJunitRunner
,所以您需要使用
自己初始化 mocks
MockitoAnnotations.initMocks(java.lang.Object testClass)
我遇到了同样的问题并尝试了 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);
}
}
除了接受的答案之外,如果您使用的是 spring-boot,使用 @MockBean 注释(创建模拟并将其添加为bean 到上下文,如果存在则替换它):
@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 加载不需要的实例,然后它们被替换通过嘲笑。这是一种浪费,并且可能具有您不 want/can 不加载的传递依赖项。始终建议为测试加载最小 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;
}
我有一个 class A,它使用 3 个不同的 classes 和自动装配
public class A () {
@Autowired
private B b;
@Autowired
private C c;
@Autowired
private D d;
}
在测试它们时,我只想将 classes(B 和 C)中的 2 个作为模拟,并让 class D 正常自动装配 运行,此代码对我不起作用:
@RunWith(MockitoJUnitRunner.class)
public class aTest () {
@InjectMocks
private A a;
@Mock
private B b;
@Mock
private C c;
@Autowired
private D d;
}
甚至可以这样做吗?
应该是这样的
@RunWith(SpringJUnit4ClassRunner.class)
public class aTest () {
@Mock
private B b;
@Mock
private C c;
@Autowired
@InjectMocks
private A a;
}
如果您希望 D
成为 Autowired
,则无需在 Test
class 中执行任何操作。您的 Autowired
A
应该有正确的 D
实例。
此外,我认为您需要使用 SpringJUnit4ClassRunner
才能使 Autowiring
正常工作,并正确设置 contextConfiguration
。
因为您没有使用 MockitoJunitRunner
,所以您需要使用
mocks
MockitoAnnotations.initMocks(java.lang.Object testClass)
我遇到了同样的问题并尝试了 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);
}
}
除了接受的答案之外,如果您使用的是 spring-boot,使用 @MockBean 注释(创建模拟并将其添加为bean 到上下文,如果存在则替换它):
@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 加载不需要的实例,然后它们被替换通过嘲笑。这是一种浪费,并且可能具有您不 want/can 不加载的传递依赖项。始终建议为测试加载最小 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;
}