Reputation: 47
I faced with problem while testing data rest repositories. I call rest resource and check if it gets me proper json. But for pre-population data I don't want to use in memory db, so I mocked repository method invocation.
@MockBean
private CommentRepository commentRepository;
and did this
given(commentRepository.findOne(1L)).willReturn(comment);
And now, while calling "/comments/1" I get 404 error, so data rest didn't expose my repository. The main question is "How can we mock repository method for getting data from database?"
My test class:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommentTest
{
@Autowired
private TestRestTemplate restTemplate;
@MockBean
private CommentRepository commentRepository;
@Before
public void setup()
{
Comment comment = new Comment();
comment.setText("description");
comment.setCommentId(1L);
given(commentRepository.findOne(1L)).willReturn(comment);
}
@Test
public void shouldCheckCommentGetResource()
{
ParameterizedTypeReference<Resource<Comment>> responseType = new ParameterizedTypeReference<Resource<Comment>>() {};
ResponseEntity<Resource<Comment>> responseEntity =
restTemplate.exchange("/comments/1", HttpMethod.GET, null, responseType, Collections
.emptyMap());
Comment actualResult = responseEntity.getBody().getContent();
assertEquals("description", actualResult.getText());
// more assertions
}
}
As I understand, using MockBean annotation I replace current repository bean and it will not be exposed by data rest, Do we have any way to pre-populate data into db or mock invocation of repository method?
Upvotes: 2
Views: 2596
Reputation:
There is quick and dirty way to mock Spring Data Rest repositories with mockito, just in case somebody have no other options, but try to avoid this unless absolutely necessary
class MockRestRepositoryUtil {
public static <T> T mockRepository(Class<T> repositoryClass,
T springRepository) throws Exception {
Object springRepositoryImpl = AopTestUtils.getTargetObject(springRepository);
T mockRepository = mock(repositoryClass, delegatesTo(springRepositoryImpl));
Object springProxyHandler = Proxy.getInvocationHandler(springRepository);
ProxyFactory proxyFactory = extractProxyFactory(springProxyHandler);
proxyFactory.setTarget(mockRepository);
removeSpringDataAspects(proxyFactory);
return mockRepository;
}
private static ProxyFactory extractProxyFactory(Object springProxyHandler) throws Exception {
Field advisedField = springProxyHandler.getClass().getDeclaredField("advised");
advisedField.setAccessible(true);
return (ProxyFactory) advisedField.get(springProxyHandler);
}
private static void removeSpringDataAspects(ProxyFactory proxyFactory) {
Advisor[] advisors = proxyFactory.getAdvisors();
Arrays.stream(advisors)
.filter(advisor -> advisor.getAdvice().getClass().getPackage().getName()
.contains("org.springframework.data"))
.collect(toImmutableList())
.forEach(proxyFactory::removeAdvisor);
}
}
Upvotes: 0
Reputation: 12184
I do not think this is possible. Spring data registers the repository beans using a FactoryBean - in the spring-data-rest case this is EntityRepositoryFactoryBean
. So you cannot just override these beans with a mock.
For an interesting read on why mocking spring data repositories is not useful see this answer https://stackoverflow.com/a/23442457/5371736
In the same thread there is a reference to a project introducing mock support for spring-data repositories - https://stackoverflow.com/a/28643025/5371736
Upvotes: 1