繁体   English   中英

@InjectMocks 通过构造函数和设置器注入 @MockBean 无法正常工作

[英]@InjectMocks inject @MockBean by Constructor and setter not working properly

我已经通过取消@RunWith(SpringJUnit4ClassRunner.class)尝试了很多次,我尝试使用getter 和构造函数注入创建一个针对class 的测试用例。 当我使用@MockBean进行setter 注入时,@Mock 用于构造函数注入并且还使用@Mock @RunWith(SpringJUnit4ClassRunner.class)MockitoAnnotations.initMocks(this); 豆类注射。 如果我评论MockitoAnnotations.initMocks(this); 构造函数注入不起作用。 现在所有 bean 都被完美地注入了,但是@Mock beans(Contructor injection ) bean 在调用时模拟了 mthods 无法正常工作。

@Component
Class A{
}

@Component
Class B {
}

@Component
Class c{
}

@Component
Class D{
@Atowired
A a;

B b;
C c;
@Autowired
public D(B b,C c){
b=b;
c=c;
}
}

我的测试 Class 是

@RunWith(SpringJUnit4ClassRunner.class)
Class TestClass{
@MockBean
A mockA
@Mock
B mockB
@Mock
C mockC
@InjectMocks
D mockD

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);//Without this Constructor injection not working
when(mockA.getValue()).then("StringValA");
when(mockB.getValue()).then("StringValB");
when(mockC.getValue()).then("StringValC");

}
@Test
public void testMethod(){
mock.getAllValues();// It will call all injested bean method we are mocked in @before 
}
}

注入工作正常,问题属于我使用@Mock的模拟bean 方法不能正常工作意味着mockB.getValue()mockC.getValue() retun nullmockA.getValue()在我测试运行时正确返回。

如果您使用SpringJUnit4ClassRunner.class运行测试,那么您需要使用@MockBean而不是@Mock

请参考 spring 启动文档

此外,您需要使用@Autowired而不是@InjectMocks

@RunWith(SpringJUnit4ClassRunner.class)
Class TestClass{
@MockBean
A mockA
@MockBean
B mockB
@MockBean
C mockC
@Autowired
D mockD

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);//Without this Constructor injection not working
when(mockA.getValue()).then("StringValA");
when(mockB.getValue()).then("StringValB");
when(mockC.getValue()).then("StringValC");

}
@Test
public void testMethod(){
mock.getAllValues();// It will call all injested bean method we are mocked in @before 
}
}

当您使用 spring 运行程序运行测试时,您必须指定您希望作为 bean 加载的确切内容(请阅读,让 spring 知道究竟应该将哪些内容包含到应用程序上下文中)。

通常这可以通过@ContextConfiguration注解来完成。

我怀疑由于您没有指定此注释,因此 spring 并没有真正加载您的任何组件(问题中的 A、B、C 等)。

现在@MockBean基本上允许“更改”应用程序上下文以进行测试。 它通过提供一个模拟而不是应该在“常规”应用程序上下文中加载的真实 bean 来做到这一点。

在这种情况下,没有必要调用MockitoAnnotations.initMocks(this); 一旦一切配置正确,Spring 将自行注入模拟。

普通 bean 初始化方法,如SpringJUnit4ClassRunnerMockitoAnnotations.initMocks(this); 一次只处理一种类型的注入。 构造函数或自动有线注入。

@RunWith(SpringJUnit4ClassRunner.class)表示公共 class SpringJUnit4ClassRunner 扩展 BlockJUnit4ClassRunner。 SpringJUnit4ClassRunner 是 JUnit 的自定义扩展。 它将在测试运行的初始时间初始化模拟 @MockeBean 和 @bean 注释的 bean。Alsoi 也运行 bean 注入。

必须调用MockitoAnnotations.initMocks(this)方法来初始化带注释的字段。 在上面的例子中,initMocks() 在测试的基础 class 的 @Before (JUnit4) 方法中被调用。 对于 JUnit3 initMocks() 可以 go 到基础 class 的 setup() 方法。

因此,在上述问题中,您使用了 SpringJUnit4ClassRunner 和 MockitoAnnotations.initMocks(this); 它将为您使用@Mock创建两个模拟 bean 引用。 同样在上面的代码流中。

1.在SpringJUnit4ClassRunner运行之初,它会为@Mock和@MockBean注解的属性创建bean引用。之后,它将在tjis时间创建注入的bean,只发生构造函数注入

2.运行@Before并运行MockitoAnnotations.initMocks(this); 它将为@Mock 注释属性创建另一个模拟引用并仅替换直接引用。 并且此时自动接线注入运行。

  1. 运行MockitoAnnotations.initMocks(this); 您将看到 allk bean 已初始化并注入良好。 但是通过构造函数注入的 bean 不是正确的引用,这些引用是由 SpringJUnit4ClassRunner 创建的旧 bean 引用。

如果要实现单个 bean 的构造函数和自动有线注入,则必须使用手动 bean 注入进行构造函数注入。 你可以参考这里

解决方案:

@RunWith(SpringJUnit4ClassRunner.class)
Class TestClass{
@MockBean
A mockA
@MockBean
B mockB
@MockBean
C mockC
@Autowired
D mockD

@Before
public void setUp() {
mockD = new D(mockA,mockB);
MockitoAnnotations.initMocks(this);
when(mockA.getValue()).then("StringValA");
when(mockB.getValue()).then("StringValB");
when(mockC.getValue()).then("StringValC");

}
@Test
public void testMethod(){
mock.getAllValues();// It will call all injested bean method we are mocked in @before 
}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM