Reputation: 8945
I'm trying to unit test a service method. The service methods calls a spring data repository method to fetch some data. I want to mock that repository call, and supply the data myself. How to do that? Following Spring Boot documentation, when I mock the repository and call the repository method directly in my test code, the mock is working. But when I call the service method, which in turn would call the repository method, mocking isn't working. Below is the sample code:
Service class:
@Service
public class PersonService {
private final PersonRepository personRepository;
@Autowired
public PersonService(personRepository personRepository) {
this.personRepository = personRepository;
}
public List<Person> findByName(String name) {
return personRepository.findByName(name); // I'd like to mock this call
}
}
Test class:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
// http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans
@MockBean
private PersonRepository personRepository;
@Autowired
private PersonService personService;
private List<Person> people = new ArrayList<>();
@Test
public void contextLoads() throws Exception {
people.add(new Person());
people.add(new Person());
given(this.personRepository.findByName("Sanjay Patel")).willReturn(people);
assertTrue(personService.findByName("Sanjay Patel") == 2); // fails
}
}
Upvotes: 5
Views: 18481
Reputation: 6271
For Spring Data repositories you need to specifiy the bean name. Mocking via type doesn't seem to work because the repository is a dynamic proxy at runtime.
The default bean name for PersonRepository
is "personRepository", so this should work:
@MockBean("personRepository")
private PersonRepository personRepository;
Here's the complete test:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
// http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans
@MockBean("personRepository")
private PersonRepository personRepository;
@Autowired
private PersonService personService;
private List<Person> people = new ArrayList<>();
@Test
public void contextLoads() throws Exception {
people.add(new Person());
people.add(new Person());
given(this.personRepository.findByName("Sanjay Patel")).willReturn(people);
assertTrue(personService.findByName("Sanjay Patel") == 2); // fails
}
}
Upvotes: 5
Reputation: 906
Probably the repository is marked with @MockedBean annotation. I do not know if Spring can auto wire by type if the repository is a mock. You can define the @Bean method and return Mockito.mock(X.class), this should work.
Not sure you need spring for unit testing a service method though. A lighter approach would be to use solely Mockito with its @InjectMocks annotation.
Upvotes: 0