模拟Spring数据休息存储库

时间:2016-12-14 23:18:52

标签: spring rest unit-testing spring-data-rest

我在测试数据休息库时遇到了问题。我打电话给rest资源并检查它是否让我得到了正确的json。但是对于预填充数据我不想在内存db中使用,所以我模拟了存储库方法调用 @MockBean private CommentRepository commentRepository; 并做了这个

given(commentRepository.findOne(1L)).willReturn(comment);

现在,在调用“/ comments / 1”时,我收到404错误,因此数据休息时没有公开我的存储库。主要问题是“我们如何模拟存储库方法从数据库中获取数据?”
我的考试班:

    @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,它不会被数据休息公开,我们有没有办法将数据预先填充到db或模拟调用存储库方法?

2 个答案:

答案 0 :(得分:0)

我不认为这是可能的。 Spring数据使用FactoryBean注册存储库bean - 在spring-data-rest情况下,这是EntityRepositoryFactoryBean。所以你不能用mock来覆盖这些bean。

有关为什么模拟spring数据存储库无用的有趣读物,请参阅此答案https://stackoverflow.com/a/23442457/5371736

在同一个线程中,引用了一个项目,引入了对spring-data存储库的模拟支持 - https://stackoverflow.com/a/28643025/5371736

答案 1 :(得分:0)

有一种快速且肮脏的方法可以通过模仿来模拟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);
    }
}