Tuesday, July 22, 2014

Spring: Integration testing under Spring Boot application context but mocking services


Use @MockBean annotation

DEPRACATED:

So I wanted to create some integration tests for an API application that uses Spring Boot. The thing is that I needed to load the same application context as the real applicationm, because Spring Boot performs a bunch of configurations for you, and these were not being loaded in a StandAlone mode.

But also I didn't want to use real services which depend upon real data. Depending on databases for your tests creates fragile tests.

After researching on the web I found this way:


This is the typical Spring-Boot entry point class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
i<span style="font-size: xx-small;">mport org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
 
@EnableAutoConfiguration
@ComponentScan
public class MyApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
 
</span>
A base class having the logic to init the application context.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<span style="font-size: xx-small;">import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
 
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = MyApplication.class)
public abstract class BaseIntegrationTest {
 
    protected MockMvc mockMvc;
     
    @Autowired
    protected WebApplicationContext wac;
 
    @Before
    public void setup() {
        
        MockitoAnnotations.initMocks(this);
        this.mockMvc = webAppContextSetup(wac).build();
    }
}
 
</span>
An implementation class mocking a required service class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<span style="font-size: xx-small;">public class FooIntegrationTest extends BaseIntegrationTest {
 
    @Configuration
    public static class TestConfiguration {
        @Bean
        @Primary
        public FooService fooService() {
            return mock(FooService.class);
        }
    }
 
 
    @Autowired
    FooService mockFooService;
}</span>

2 comments:

  1. cant get this to work for me. TestConfiguration.fooService is never invoked. Would you have any ideas as to what I might be doing wrong?

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete