I have a @Service
bean that I need static
access to:
@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";
}
}
Usage:
@Service
public class OtherService {
public static void makeUse() {
MyBean myBean = MyBean.get();
}
}
Problem: when I write an integration junit
test for OtherService
that makes use of the stat MyBean
access, the instance
variable is always 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
}
}
Question: how can I write an integration test when using such type of static access to a spring-managed bean?
If you want to influence the @Bean
-creation, then use @Configuration
@Configuration
public class MyConfig {
@Bean
public MyBean myBean() {
return new MyBean;
}
@Bean
public OtherService otherService () {
return new OtherService(myBean());
}
}
Then mocking becomes really easy:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ITest {
@MockBean
private MyBean myBean;
@Autowired
private OtherService service;
@Test
public void test() {
// service is initialised with myBean
...
}
}
When more control is needed, then you can choose the following approach. It provides sometimes more control than just a @MockBean. In your test you can easily mock a method just before calling it. This is my preferred way.
@Configuration
public class MyConfig {
...
@Bean
public MyBean getMyBean() {
return mock( MyBean.class);
}
@Bean
public OtherService otherService () {
return new OtherService( getMyBean());
}
}
In the application you can use @Autorwired to access it AND implement method overrule/mocking easily.
@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
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.