模拟 Spring 数据剩余存储库
Mock Spring Data Rest Repository
我在测试数据存储库时遇到问题。我调用休息资源并检查它是否让我正确 json。但是对于预填充数据,我不想在内存数据库中使用,所以我模拟了存储库方法调用。
@MockBean
private CommentRepository commentRepository;
并做到了
given(commentRepository.findOne(1L)).willReturn(comment);
现在,在调用“/comments/1”时出现 404 错误,因此剩余数据没有公开我的存储库。主要问题是"How can we mock repository method for getting data from database?"
我的测试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
}
}
据我所知,使用 MockBean 注释我替换了当前存储库 bean,它不会被数据 rest 暴露,我们有没有办法将数据预填充到数据库或模拟调用存储库方法?
我认为这是不可能的。 Spring data 使用 FactoryBean 注册存储库 bean - 在 spring-data-rest 情况下,这是 EntityRepositoryFactoryBean
。所以你不能只用模拟来覆盖这些 beans。
有关为什么模拟 spring 数据存储库没有用的有趣阅读,请参阅此答案
在同一个线程中有一个项目的引用,该项目引入了对 spring 数据存储库的模拟支持 -
有一种使用 mockito 模拟 Spring Data Rest 存储库的快速而肮脏的方法,以防万一有人没有其他选择,但除非绝对必要,否则尽量避免这种情况
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);
}
}
我在测试数据存储库时遇到问题。我调用休息资源并检查它是否让我正确 json。但是对于预填充数据,我不想在内存数据库中使用,所以我模拟了存储库方法调用。
@MockBean
private CommentRepository commentRepository;
并做到了
given(commentRepository.findOne(1L)).willReturn(comment);
现在,在调用“/comments/1”时出现 404 错误,因此剩余数据没有公开我的存储库。主要问题是"How can we mock repository method for getting data from database?"
我的测试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
}
}
据我所知,使用 MockBean 注释我替换了当前存储库 bean,它不会被数据 rest 暴露,我们有没有办法将数据预填充到数据库或模拟调用存储库方法?
我认为这是不可能的。 Spring data 使用 FactoryBean 注册存储库 bean - 在 spring-data-rest 情况下,这是 EntityRepositoryFactoryBean
。所以你不能只用模拟来覆盖这些 beans。
有关为什么模拟 spring 数据存储库没有用的有趣阅读,请参阅此答案
在同一个线程中有一个项目的引用,该项目引入了对 spring 数据存储库的模拟支持 -
有一种使用 mockito 模拟 Spring Data Rest 存储库的快速而肮脏的方法,以防万一有人没有其他选择,但除非绝对必要,否则尽量避免这种情况
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);
}
}