Am developing MicroServices in springBoot. Am writing unit test for Service and DAO layer. When I use @SpringBootTest it starting application on build. But It should not start application when I run unit test. I used @RunWith(SpringRunner.class), But am unable to @Autowired class instance in junit class. How can I configure junit test class that should not start application and how to @Autowired class instance in junit class.
4 Answers
With Spring Boot you can start a sliced version of your application for your tests. This will create a Spring Context that only contains a subset of your beans that are relevant e.g. only for your web layer (controllers, filters, converters, etc.): @WebMvcTest.
There is a similar annotation that can help you test your DAOs as it only populates JPA and database relevant beans (e.g. EntitiyManager, Datasource, etc.): @DataJpaTest.
If you want to autowire a bean that is not part of the Spring Test Context that gets created by the annotatiosn above, you can use a @TestConfiguration to manually add any beans you like to the test context
@WebMvcTest(PublicController.class) class PublicControllerTest { @Autowired private MockMvc mockMvc; @TestConfiguration static class TestConfig { @Bean public EntityManager entityManager() { return mock(EntityManager.class); } @Bean public MeterRegistry meterRegistry() { return new SimpleMeterRegistry(); } } } Comments
Use MockitoJUnitRunner for JUnit5 testing if you don't want to start complete application.
Any Service, Repository and Interface can be mocked by @Mock annotation.
@InjectMocks is used over the object of Class that needs to be tested.
Here's an example to this.
@RunWith(MockitoJUnitRunner.class) @SpringBootTest public class AServiceTest { @InjectMocks AService aService; @Mock ARepository aRepository; @Mock UserService userService; @Before public void setUp() { // MockitoAnnotations.initMocks(this); // anything needs to be done before each test. } @Test public void loginTest() { Mockito.when(aRepository.findByUsername(ArgumentMatchers.anyString())).thenReturn(Optional.empty()); String result = aService.login("test"); assertEquals("false", result); } 5 Comments
@ExtendWith(MockitoExtension.class), otherwise the mocks aren't initialized.@SpringBootTest along with RunWith(MockitoJunitRunner.class which is wrong. It interferers with the Mockito Runner and still loads the whole app. You need to remove SpringBootTest.Depending your test setup, if you don't want to autowire a mock but the "real thing", You could simply annotate your test class to include exactly the classes you need (plus their transitive dependencies if necessary)
For example :
@SpringJUnitConfig({ SimpleMeterRegistry.class }) or
@SpringJUnitConfig @Import({ SimpleMeterRegistry.class }) or
@SpringJUnitConfig @ContextConfiguration(classes = { SimpleMeterRegistry.class }) See working JUnit5 based samples in here Spring Boot Web Data JDBC allin .
1 Comment
To avoid running the whole app, include the following Mockito annotations, and exclude @SpringBootTest.
@RunWith(MockitoJUnitRunner.class) @ExtendWith(MockitoExtension.class) The final unit test is:
@RunWith(MockitoJUnitRunner.class) // No @SpringBootTest! just Mockito RunWith/ExtendWith @ExtendWith(MockitoExtension.class) class Ar11ApplicationTest { @Mock // what we're mocking Ar11ApplicationService ar11ApplicationService; @Mock // what we're mocking EmailService emailService; @InjectMocks // what we're actually testing Ar11Application ar11Application; @BeforeEach void setUp() throws Exception { // Set up an example mock behavior Mockito.when(ar11ApplicationService.processEligibleRecords( Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()) .thenReturn(new Ar11ResultBean(500)); } @Test void runTest1() throws Exception { //.. } (But be aware that if you have some App Test Properties YAML, you need @SpringBootTest to read them in -- e.g. application-test.yaml. In that case you can't avoid @SpringBootTest. It can be used with @Import to import custom mock classes for any objects -- example here.)