在另一个 bean 的构造函数中插入 bean 的存根方法
Stubbing methods of injected beans in another bean's constructors
我使用构造函数注入测试了一个 Spring bean。注入的 bean 在测试用例中被定义为 @MockBean
并且还定义了适当的存根:当调用模拟 bean 的某个方法时,它应该 return 一个模拟对象。
当我启动测试用例时,我得到一个 NullPointerException
,因为存根不起作用 – 方法 returns 总是 null
.
这里是要测试的对象的构造函数:
@Autowired
public MyBeanToTest(msTemplate jmsTemplate) throws JMSException {
this.jmsTemplate = jmsTemplate;
this.cf = this.jmsTemplate.getConnectionFactory(); // cf is always null
cf.createSession(); // NPE
}
这是测试用例:
@SpringBootTest
public class MyTestClass {
@Autowired
MyBeanToTest myBeanToTest;
@MockBean
private JmsTemplate jmsTemplate;
@Mock
private static ConnectionFactory connectionFactory;
@Test
public void testSomething() {
...
when( jmsTemplate.getConnectionFactory() ).thenReturn( connectionFactory );
...
}
}
我假设调用构造函数时定义的存根尚未激活。
知道如何让它发挥作用吗?
您必须使用静态存根,这样它才能存在并在创建上下文之前进行配置。
另一种更简洁的方法是不在构造函数中调用任何内容,而是根据需要使用 cf.createSession();
创建会话(它仍然可以是单例)。
另一种方法是根本不使用@MockBean,而只是自己创建GegugProcessingSoapServices
。
你的假设是正确的。最好的办法是“手动”创建 bean,而不是让 Spring 自己调用构造函数。为此,将 @Configuration
class 添加到具有相应 @Bean
方法的测试中。
未经测试的例子:
@SpringBootTest
public class MyTestClass {
@Configuration
static class MyTestClassConfiguration {
@Bean
MyBeanToTest myBeanToTest(jmsTemplate jmsTemplate) {
// Too bad that this is not within the test…
when(jmsTemplate.getConnectionFactory())
.thenReturn(connectionFactory);
…
}
}
}
@AutoWired
不适用于正在测试的 class。它不会将 bean 带入构造函数。
解决方案可以使用 Mockito @InjectMock
,或者自己创建 class 并在构造函数中使用模拟(这通常是一个好习惯):
MyBeanToTest myBeanToTest = new MyBeanToTest(connectionFactory)
我建议不要模拟而是存根 JmsTemplate
bean。
@SpringBootTest
public class MyTestClass {
@Autowired
MyBeanToTest myBeanToTest;
@Autowired
private JmsTemplate jmsTemplate;
@Mock
private static ConnectionFactory connectionFactory;
@TestConfiguration
static class Config {
@Bean
public JmsTemplate jmsTemplate() {
return new JmsTemplate() {
public ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
}
}
}
@Test
public void testSomething() {
...
}
}
我使用构造函数注入测试了一个 Spring bean。注入的 bean 在测试用例中被定义为 @MockBean
并且还定义了适当的存根:当调用模拟 bean 的某个方法时,它应该 return 一个模拟对象。
当我启动测试用例时,我得到一个 NullPointerException
,因为存根不起作用 – 方法 returns 总是 null
.
这里是要测试的对象的构造函数:
@Autowired
public MyBeanToTest(msTemplate jmsTemplate) throws JMSException {
this.jmsTemplate = jmsTemplate;
this.cf = this.jmsTemplate.getConnectionFactory(); // cf is always null
cf.createSession(); // NPE
}
这是测试用例:
@SpringBootTest
public class MyTestClass {
@Autowired
MyBeanToTest myBeanToTest;
@MockBean
private JmsTemplate jmsTemplate;
@Mock
private static ConnectionFactory connectionFactory;
@Test
public void testSomething() {
...
when( jmsTemplate.getConnectionFactory() ).thenReturn( connectionFactory );
...
}
}
我假设调用构造函数时定义的存根尚未激活。 知道如何让它发挥作用吗?
您必须使用静态存根,这样它才能存在并在创建上下文之前进行配置。
另一种更简洁的方法是不在构造函数中调用任何内容,而是根据需要使用 cf.createSession();
创建会话(它仍然可以是单例)。
另一种方法是根本不使用@MockBean,而只是自己创建GegugProcessingSoapServices
。
你的假设是正确的。最好的办法是“手动”创建 bean,而不是让 Spring 自己调用构造函数。为此,将 @Configuration
class 添加到具有相应 @Bean
方法的测试中。
未经测试的例子:
@SpringBootTest
public class MyTestClass {
@Configuration
static class MyTestClassConfiguration {
@Bean
MyBeanToTest myBeanToTest(jmsTemplate jmsTemplate) {
// Too bad that this is not within the test…
when(jmsTemplate.getConnectionFactory())
.thenReturn(connectionFactory);
…
}
}
}
@AutoWired
不适用于正在测试的 class。它不会将 bean 带入构造函数。
解决方案可以使用 Mockito @InjectMock
,或者自己创建 class 并在构造函数中使用模拟(这通常是一个好习惯):
MyBeanToTest myBeanToTest = new MyBeanToTest(connectionFactory)
我建议不要模拟而是存根 JmsTemplate
bean。
@SpringBootTest
public class MyTestClass {
@Autowired
MyBeanToTest myBeanToTest;
@Autowired
private JmsTemplate jmsTemplate;
@Mock
private static ConnectionFactory connectionFactory;
@TestConfiguration
static class Config {
@Bean
public JmsTemplate jmsTemplate() {
return new JmsTemplate() {
public ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
}
}
}
@Test
public void testSomething() {
...
}
}