@InjectMocks 通过 Constructor 注入 @MockBean 并且 setter 无法正常工作
@InjectMocks inject @MockBean by Constructor and setter not working properly
我试了很多次不唱@RunWith(SpringJUnit4ClassRunner.class)
我试图用 getter 和构造函数注入创建一个针对 class 的测试用例。当我使用 @MockBean
进行 setter 注入时,@Mock
进行构造函数注入并且还使用 @RunWith(SpringJUnit4ClassRunner.class)
和 MockitoAnnotations.initMocks(this);
bean 注入。
如果我评论 MockitoAnnotations.initMocks(this);
构造函数注入不起作用。
现在所有的 bean 都被完美地注入了,但是 @Mock
beans(构造函数注入)bean 模拟方法在调用时无法正常工作。
@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
}
}
注入工作正常,问题属于我使用的 bean 的模拟方法 @Mock
工作不正常意味着 mockB.getValue()
和 mockC.getValue()
重新调整 null
但是mockA.getValue()
return 当我测试 运行.
时正确
当您 运行 使用 spring 运行ner 进行测试时,您必须指定您希望将什么作为 bean 加载(阅读,让 spring 知道什么完全应该包含在应用程序上下文中)。
通常这可以通过 @ContextConfiguration
注释来完成。
我怀疑由于您没有指定此注释,spring 并没有真正加载您的任何组件(问题中的 A、B、C 等)。
现在 @MockBean
基本上允许 "altering" 应用程序上下文用于测试目的。它通过提供模拟而不是应该加载到 "regular" 应用程序上下文中的真实 bean 来做到这一点。
在这种情况下,没有必要调用 MockitoAnnotations.initMocks(this);
Spring 将在所有配置正确后自行注入模拟。
如果您 运行 是 SpringJUnit4ClassRunner.class
的测试,那么您需要使用 @MockBean
而不是 @Mock
。
请参考spring开机documentation
此外,您需要使用 @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
}
}
解决方案:
@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
}
}
Normal bean initialize methods like SpringJUnit4ClassRunner
or MockitoAnnotations.initMocks(this);
handling only one type injection at a time. Either constructor or Auto wired injection.
@RunWith(SpringJUnit4ClassRunner.class)
表示 public class SpringJUnit4Class运行ner 扩展了 BlockJUnit4Class运行ner。 SpringJUnit4Class运行ner 是 JUnit 的自定义扩展。它将在测试的初始时间初始化模拟 @MockeBean 和 @bean anotted beans run.Alsoi 运行nig bean 注入。
必须调用 MockitoAnnotations.initMocks(this)
方法来初始化带注释的字段。在上面的示例中,initMocks() 在测试基础 class 的 @Before (JUnit4) 方法中被调用。对于 JUnit3 initMocks() 可以转到基 class.
的 setup() 方法
所以在上面的问题中你使用了 SpringJUnit4Class运行ner 和 MockitoAnnotations.initMocks(this);它将创建两个模拟 bean 引用,您可以为它们使用 @Mock
。同样在上面的代码流程中。
1.At 开始 SpringJUnit4ClassRunner
运行 它将为 @Mock 和 @MockBean 创建 bean 引用,注释 attributes.after 它只会在 tjis 时间创建注入的 bean发生构造函数注入
2.Run @Before 和 运行 MockitoAnnotations.initMocks(this);
它将为 @Mock 注释属性创建另一个模拟引用并仅替换直接引用。和此时自动有线注入运行。
- 在 运行 宁
MockitoAnnotations.initMocks(this);
之后,您将看到 allk bean 已初始化并注入良好。但是通过构造函数注入的 bean 那些 bean 不是正确的引用,这些引用了由 SpringJUnit4Class运行ner. 创建的旧 bean 引用
如果要为单个bean 实现构造函数和自动注入注入,则必须使用手动注入bean 来进行构造函数注入。你可以参考here
我试了很多次不唱@RunWith(SpringJUnit4ClassRunner.class)
我试图用 getter 和构造函数注入创建一个针对 class 的测试用例。当我使用 @MockBean
进行 setter 注入时,@Mock
进行构造函数注入并且还使用 @RunWith(SpringJUnit4ClassRunner.class)
和 MockitoAnnotations.initMocks(this);
bean 注入。
如果我评论 MockitoAnnotations.initMocks(this);
构造函数注入不起作用。
现在所有的 bean 都被完美地注入了,但是 @Mock
beans(构造函数注入)bean 模拟方法在调用时无法正常工作。
@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
}
}
注入工作正常,问题属于我使用的 bean 的模拟方法 @Mock
工作不正常意味着 mockB.getValue()
和 mockC.getValue()
重新调整 null
但是mockA.getValue()
return 当我测试 运行.
当您 运行 使用 spring 运行ner 进行测试时,您必须指定您希望将什么作为 bean 加载(阅读,让 spring 知道什么完全应该包含在应用程序上下文中)。
通常这可以通过 @ContextConfiguration
注释来完成。
我怀疑由于您没有指定此注释,spring 并没有真正加载您的任何组件(问题中的 A、B、C 等)。
现在 @MockBean
基本上允许 "altering" 应用程序上下文用于测试目的。它通过提供模拟而不是应该加载到 "regular" 应用程序上下文中的真实 bean 来做到这一点。
在这种情况下,没有必要调用 MockitoAnnotations.initMocks(this);
Spring 将在所有配置正确后自行注入模拟。
如果您 运行 是 SpringJUnit4ClassRunner.class
的测试,那么您需要使用 @MockBean
而不是 @Mock
。
请参考spring开机documentation
此外,您需要使用 @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
}
}
解决方案:
@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
}
}
Normal bean initialize methods like
SpringJUnit4ClassRunner
orMockitoAnnotations.initMocks(this);
handling only one type injection at a time. Either constructor or Auto wired injection.
@RunWith(SpringJUnit4ClassRunner.class)
表示 public class SpringJUnit4Class运行ner 扩展了 BlockJUnit4Class运行ner。 SpringJUnit4Class运行ner 是 JUnit 的自定义扩展。它将在测试的初始时间初始化模拟 @MockeBean 和 @bean anotted beans run.Alsoi 运行nig bean 注入。
MockitoAnnotations.initMocks(this)
方法来初始化带注释的字段。在上面的示例中,initMocks() 在测试基础 class 的 @Before (JUnit4) 方法中被调用。对于 JUnit3 initMocks() 可以转到基 class.
所以在上面的问题中你使用了 SpringJUnit4Class运行ner 和 MockitoAnnotations.initMocks(this);它将创建两个模拟 bean 引用,您可以为它们使用 @Mock
。同样在上面的代码流程中。
1.At 开始 SpringJUnit4ClassRunner
运行 它将为 @Mock 和 @MockBean 创建 bean 引用,注释 attributes.after 它只会在 tjis 时间创建注入的 bean发生构造函数注入
2.Run @Before 和 运行 MockitoAnnotations.initMocks(this);
它将为 @Mock 注释属性创建另一个模拟引用并仅替换直接引用。和此时自动有线注入运行。
- 在 运行 宁
MockitoAnnotations.initMocks(this);
之后,您将看到 allk bean 已初始化并注入良好。但是通过构造函数注入的 bean 那些 bean 不是正确的引用,这些引用了由 SpringJUnit4Class运行ner. 创建的旧 bean 引用
如果要为单个bean 实现构造函数和自动注入注入,则必须使用手动注入bean 来进行构造函数注入。你可以参考here