6

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 4

4

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(); } } } 
Sign up to request clarification or add additional context in comments.

Comments

3

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

The Requirement should be connect to database to fetch records. If mock object we can't get real time data. Is this possible using @ContextConfiguration
@user3410249 if you want to perform unit testing, you can mock the database records itself. As MockitoJUnitRunner is the fastest way to runt he tests without running application or external db's. Option is you cn use Mockito.when(...).thenReturn() to return mocked records from database, which is better way for unit testing. But if you want realtime connection to db, your application will start.
Thank you. I got better understand.
you missed an additional annotation that's required, @ExtendWith(MockitoExtension.class), otherwise the mocks aren't initialized.
Also, you still have @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.
2

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

ah bum, Autowired doesn't work with this. Please clarify how to use it.
2

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.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.