![](/img/trans.png)
[英]How to inject final class such as String into constructor of class annotated with @InjectMocks in Mockito 3
[英]@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 null
但mockA.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 初始化方法,如
SpringJUnit4ClassRunner
或MockitoAnnotations.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 注释属性创建另一个模拟引用并仅替换直接引用。 并且此时自动接线注入运行。
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.