我有一个我需要 static
访问的 @Service
bean:
@Service
public class MyBean implements InitializingBean {
private static MyBean instance;
@Override
public void afterPropertiesSet() throws Exception {
instance = this;
}
public static MyBean get() {
return instance;
}
public String someMethod(String param) {
return "some";
}
}
用法:
@Service
public class OtherService {
public static void makeUse() {
MyBean myBean = MyBean.get();
}
}
问题:当我编写用于使用stat MyBean
访问的OtherService
集成junit
测试时,instance
变量始终为null。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ITest {
@Autowired
private OtherService service;
@MockBean
private MyBean myBean;
@Before
public void mock() {
Mockito.when(myBean.someMethod(any()).thenReturn("testvalue");
}
@Test
public void test() {
service.makeUse(); //NullPointerException, as instance is null in MyBean
}
}
问题:在使用这种类型的静态访问对弹簧管理的bean时如何编写集成测试?
如果要影响 @Bean
-greation,请使用 @Configuration
@Configuration
public class MyConfig {
@Bean
public MyBean myBean() {
return new MyBean;
}
@Bean
public OtherService otherService () {
return new OtherService(myBean());
}
}
然后,模拟变得非常容易:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ITest {
@MockBean
private MyBean myBean;
@Autowired
private OtherService service;
@Test
public void test() {
// service is initialised with myBean
...
}
}
当需要更多的控件时,您可以选择以下方法。有时,它提供的控制不仅仅是@mockbean。在您的测试中,您可以在调用之前轻松模拟一种方法。这是我首选的方式。
@Configuration
public class MyConfig {
...
@Bean
public MyBean getMyBean() {
return mock( MyBean.class);
}
@Bean
public OtherService otherService () {
return new OtherService( getMyBean());
}
}
在应用程序中,您可以使用@AutorWired访问它并实现方法覆盖/模拟。
@RunWith(SpringRunner.class)
@SpringBootTest
public class AnotherTest {
@Autowired
private MyBean myBean;
@Autowired
private OtherService service;
@Test
public void test() {
when( myBean.method( a, b)).thenReturn( something);
service.doSomething( ....); // with myBean.method() overruled
}
}