Reputation: 67
I was wondering how @autowire works here?
I am tring to practise how to use mock to do unit test in Spring.
Here is the code for my simple UserService
@Service
public class UserService {
@Autowired
UserRepository userRepository;
public User findByName(String name) {
return userRepository.findByName(name);
}
}
Here is the code for my unit test.
package com.geotab.dna.springtestdemo.services;
import com.geotab.dna.springtestdemo.entities.User;
import com.geotab.dna.springtestdemo.repositories.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
public class UserServiceTest {
@TestConfiguration
static class UserServiceImplContextConfiguration {
@Bean
public UserService userService() {
UserService userService = new UserService();
return userService;
}
}
@Autowired
private UserService userService;
@MockBean
private UserRepository userRepository;
@Test
public void whenFindByName_thenReturnUser() {
//given
String name = "alex";
User user = new User(name);
Mockito.when(userRepository.findByName(name)).thenReturn(user);
//when
User found = userService.findByName("alex");
//then
assert (user.getName().equals(found.getName()));
}
}
I got the above code from a blog, it works. But I am confused that why UserRepository could be injected into UserService? Because at the very beginning I am thinking that UserService.UserRepository will be null.
Upvotes: 1
Views: 1071
Reputation: 27078
Just look at different parts of the program what you have
@RunWith(SpringRunner.class)
you are using a runner class provided by Spring@Autowire
which makes spring search for the class in its application context when it encoutners this statement. Now coming to the point how does userRepository object gets injected into userService. This is because of @MockBean
. From the documentation it says
Annotation that can be used to add mocks to a Spring ApplicationContext. Can be used as a class level annotation or on fields in either @Configuration classes, or test classes that are @RunWith the SpringRunner.
This means when spring encounters @MockBean
, it adds that bean to application context. Hence when it encounters @Autowired
on userRepository inside userService, it injects the mock instance it has.
This annotation was introduced in a few releases back. Before that we had to declare a mock using @Mock
and use @InjectMocks
or using construction injection.
Look at this question for more on the differente between @Mock
and @MockBean
Upvotes: 1