gpt4 book ai didi

java - 如何对使用存储库的服务层进行 Spring 单元测试?

转载 作者:行者123 更新时间:2023-12-02 12:24:21 25 4
gpt4 key购买 nike

我正在开发一个Spring REST应用程序,并且有一个服务来访问数据库(使用存储库)并恢复最后N个文档(我正在使用MongoDB )。

所以,我的服务具有以下功能:

@Async
public CompletableFuture<List<MessageLogViewDto>> listLogs(int total) {
// Request the entities using PageRequest to list only last N registers ordered by DATE (DESC). I don't known a better way to do this!
PageRequest page = new PageRequest(0, total, Sort.Direction.DESC, "Date");
Page<MessageLog> messages = logRepo.findAll(page);

// Convert the Entity to DTO
List<MessageLogViewDto> messageList = messages.getContent().stream().map(
message -> convertDto.toMessageLogView(message)).collect(Collectors.toList());

return CompletableFuture.completedFuture(messageList);
}

(convertDto是将实体转换为Dto的类)。

好的,如何对此进行单元测试?我在几个博客上读到,单元测试不应连接到数据库。如果我使用真正的测试数据库,这个单元测试可以变得非常简单,但我想知道在没有数据库的情况下进行此测试的更好方法是什么(如果可能)。

我可以模拟存储库和函数 findAll ,但是如果我模拟 findAll 方法,我也必须模拟返回值。我不知道如何 mock Page<Object>响应,因为Page是一个接口(interface),我必须实现模拟中的所有方法。

对于我的测试,我正在考虑创建 3 个随机 message实体,具有不同的日期,并检查是否只返回最后一条消息。

像这样:

@Test
public void shouldReturnLastMessage() {
int total = 1;

// mock findAll
// mock first entity
// mock a second entity
// mock a third entity
// ??? = must return a Page<MessageLog> with 3 entitys, how?
when(dbLogRepoMock.findAll(any(PageRequest.class))).thenReturn(???);

// call the service
List<MessageLogViewDto> result = logService.listLogs(total).join();

// check returned value
assertThat(result.size()).isEqualTo(total);
assertThat(result.get(0).getMensagem()).isEqualTo("third message"); // last message

// check if repository was called
verify(dbLogRepoMock).findAll(any(PageRequest.class));
}

有什么帮助吗?

最佳答案

这可能是一个略有争议的观点,但我将只专注于您的转换器的单元测试,因为此方法中没有其他有意义的自定义逻辑。

看看它的方法:

// 1 - Create an instance of a Spring class
PageRequest page = new PageRequest(0, total, Sort.Direction.DESC, "Date");
// 2 - Query a Spring Repository with the Spring Class
Page<MessageLog> messages = logRepo.findAll(page);

// 3 - CUSTOM LOGIC to convert result to custom DTO class
List<MessageLogViewDto> messageList = messages.getContent().stream().map(
message -> convertDto.toMessageLogView(message)).collect(Collectors.toList());

// 4 - Return a Java standard CompleteableFuture
return CompletableFuture.completedFuture(messageList);

即使您要为此方法编写单元测试,

1 是简单的类实例化2 使用 1 的结果 - 但无论如何你都会创建一个模拟响应,所以它不会有意义地练习 1。3 是您的转换器逻辑,您可以直接为其编写独立测试4 正在利用核心 Java 功能,您不太可能发现错误

另外,看看方法的签名:

public CompletableFuture<List<MessageLogViewDto>> listLogs(int total) {

它接受一个整数 total并返回 CompleteableFuture (我们不关心测试它的实现,因为它不是此方法的核心功能/是内置的)包含元素列表。假设大小列表total

如果不实际访问数据库,您就必须将返回的数据模拟为预期大小。确定结果大小的实际逻辑是数据访问框架的一部分,因此您甚至无法验证输出数据大小实际上与方法的输入参数匹配。我估计没有多大值(value)。

我通常不关注单元测试数据访问方法,这些方法只是访问和返回数据,没有任何有意义的逻辑。在这种情况下,唯一有意义的逻辑出现在您的转换器中,因此我将重点测试它。

您可能会提取如下方法:

List<MessageLogViewDTO> convertMessageLogsToMessageLogViewDTO(List<MessageLog> messages) {
return messages.getContent().stream().map(
message -> convertDto.toMessageLogView(message)).collect(Collectors.toList());
}

然后您可以简单地使用各种情况(有效数据、空/空列表等)测试该方法。

关于java - 如何对使用存储库的服务层进行 Spring 单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45552659/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com