你好,我们又见面了。这是 STEP_6 的最后一篇文章,我们将在其中讨论向JRTB-6任务添加功能。在前面的两篇文章(第 1 部分、第 2 部分)中,我们已经准备好了您所需的几乎所有内容。这部分是该过程的高潮。对于所有从一开始就读过本系列文章的人,我们深表敬意。这意味着您有足够的动力去找到一份好工作。现在让我们言归正传吧。
我们实施 JRTB-6
这次我们将从电报机器人一侧执行任务,因为更新数据库的工作已全部完成,数据库实体已配置并准备好工作。让我们向CommandName添加一个新值- LIST_GROUP_SUB:LIST_GROUP_SUB("/listGroupSub");
让我们创建一个ListGroupSubCommand 命令:
package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.telegram.telegrambots.meta.api.objects.Update;
import javax.ws.rs.NotFoundException;
import java.util.stream.Collectors;
import static com.github.javarushcommunity.jrtb.command.CommandUtils.getChatId;
/**
* {@link Command} for getting list of {@link GroupSub}.
*/
public class ListGroupSubCommand implements Command {
private final SendBotMessageService sendBotMessageService;
private final TelegramUserService telegramUserService;
public ListGroupSubCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
this.sendBotMessageService = sendBotMessageService;
this.telegramUserService = telegramUserService;
}
@Override
public void execute(Update update) {
//todo add exception handling
TelegramUser telegramUser = telegramUserService.findByChatId(getChatId(update))
.orElseThrow(NotFoundException::new);
String message = "Я нашел все подписки на группы: \n\n";
String collectedGroups = telegramUser.getGroupSubs().stream()
.map(it -> "Группа: " + it.getTitle() + " , ID = " + it.getId() + " \n")
.collect(Collectors.joining());
sendBotMessageService.sendMessage(telegramUser.getChatId(), message + collectedGroups);
}
}
这里一切都尽可能简单 - 我们使用现有的 chat_id 获取用户,并且他对组的所有订阅都将收集在他的对象中。我们在第二部分中对此进行了设置。再次,我添加了//todo,这样我就不会忘记添加对操作期间可能出现的异常的处理。下一步是通过向 CommandContainer 添加新命令来更新 CommandContainer :
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
基本上就是这样:现在您需要编写更多测试,更新/help命令(添加新命令的描述)并通过 Telegram 测试新功能。让我们为ListGroupSubCommand编写一个测试。由于命令的逻辑并不典型,因此我们将编写一个测试,而不像之前那样 绑定到AbstractCommandTest类:
package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.github.javarushcommunity.jrtb.command.CommandName.LIST_GROUP_SUB;
@DisplayName("Unit-level testing for ListGroupSubCommand")
public class ListGroupSubCommandTest {
@Test
public void shouldProperlyShowsListGroupSub() {
//given
TelegramUser telegramUser = new TelegramUser();
telegramUser.setActive(true);
telegramUser.setChatId("1");
List<GroupSub> groupSubList = new ArrayList<>();
groupSubList.add(populateGroupSub(1, "gs1"));
groupSubList.add(populateGroupSub(2, "gs2"));
groupSubList.add(populateGroupSub(3, "gs3"));
groupSubList.add(populateGroupSub(4, "gs4"));
telegramUser.setGroupSubs(groupSubList);
SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);
Mockito.when(telegramUserService.findByChatId(telegramUser.getChatId())).thenReturn(Optional.of(telegramUser));
ListGroupSubCommand command = new ListGroupSubCommand(sendBotMessageService, telegramUserService);
Update update = new Update();
Message message = Mockito.mock(Message.class);
Mockito.when(message.getChatId()).thenReturn(Long.valueOf(telegramUser.getChatId()));
Mockito.when(message.getText()).thenReturn(LIST_GROUP_SUB.getCommandName());
update.setMessage(message);
String collectedGroups = "Я нашел все подписки на группы: \n\n" +
telegramUser.getGroupSubs().stream()
.map(it -> "Группа: " + it.getTitle() + " , ID = " + it.getId() + " \n")
.collect(Collectors.joining());
//when
command.execute(update);
//then
Mockito.verify(sendBotMessageService).sendMessage(telegramUser.getChatId(), collectedGroups);
}
private GroupSub populateGroupSub(Integer id, String title) {
GroupSub gs = new GroupSub();
gs.setId(id);
gs.setTitle(title);
return gs;
}
}
让我们更新 /help 命令
在我们的例子中,/help命令充当使用机器人的文档,因此我们必须记住更新它,以便用户可以使用它。我们添加了两个命令,所以让我们更新即将出现的文本:public static final String HELP_MESSAGE = String.format("✨Дотупные команды✨\n\n"
+ "Начать\\закончить работу с ботом:\n"
+ "%s - начать работу со мной\n"
+ "%s - приостановить работу со мной\n\n"
+ "Работа с подписками на группы:\n"
+ "%s - подписаться на группу статей\n"
+ "%s - получить список групп, на которые подписан\n\n"
+ "%s - получить помощь в работе со мной\n"
+ "%s - получить мою статистику использования\n",
START.getCommandName(), STOP.getCommandName(), ADD_GROUP_SUB.getCommandName(),
LIST_GROUP_SUB.getCommandName(), HELP.getCommandName(), STAT.getCommandName());
我还更新了机器人响应的文本:我这样做是为了始终与用户使用名字,否则就会有“你”和“你”......现在至少可以创建机器人工作中的某种联系。
测试更新后的机器人
我们在本地启动我们的机器人并执行以下操作:- 我们执行/start命令以确保测试用例中的用户已添加到数据库中。
- 我们执行/help命令 - 我们检查一切是否正常,如我们所愿。
- 接下来我们执行/addGroupSub命令。
- 从建议的组 ID 列表中,我们添加了几个组 ID。
- 我们运行/listGroupSub命令以确保组已注册给用户。
application.properties:
spring.datasource.url=jdbc:mysql://jrtb-db:3306/jrtb_db?characterEncoding=UTF-8
application-test.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/dev_jrtb_db?characterEncoding=UTF-8
docker-compose.yml (добавил последнюю строку):
jrtb-db:
image: mysql:5.7
restart: always
environment:
MYSQL_USER: ${BOT_DB_USERNAME}
MYSQL_PASSWORD: ${BOT_DB_PASSWORD}
MYSQL_DATABASE: 'jrtb_db'
MYSQL_ROOT_PASSWORD: 'root'
ports:
- '3306:3306'
expose:
- '3306'
command: --character-set-server=utf8 --collation-server=utf8_general_ci
docker-compose-test.yml (добавил последнюю строку)
jrtb-db-dev:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: 'dev_jrtb_db'
# So you don't have to use root, but you can if you like
MYSQL_USER: 'dev_jrtb_db_user'
# You can use whatever password you like
MYSQL_PASSWORD: 'dev_jrtb_db_password'
# Password for root access
MYSQL_ROOT_PASSWORD: 'root'
ports:
# <Port exposed> : < MySQL Port running inside container>
- '3306:3306'
expose:
# Opens port 3306 on the container
- '3306'
command: --character-set-server=utf8 --collation-server=utf8_general_ci
在这些更新之后,您需要删除数据库中的所有数据并重新开始。擦除非常简单:您需要运行命令: docker-compose -f docker-compose-test.yml down ,然后所有数据和数据库都会被删除。并使用更新的编码再次运行它: docker-compose -f docker-compose-test.uml up 数据库已准备就绪。让我们启动更新的应用程序并看一下。我会快速回顾一下并向您展示结果:现在我们得到了我们想要的结果。现在这看起来像是事实。
结尾
现在我想我们可以完成这一步了。已经做了很多,真的很多。让我们将应用程序版本更新为0.5.0-SNAPSHOT和 RELEASE_NOTES。
# 发行说明 ## 0.5.0-SNAPSHOT * JRTB-5:添加了群组订阅功能 * JRTB-6:添加了获取群组订阅列表的功能。
然后一切都像往常一样:我们创建一个包含所有更改的新提交。主要是添加此步骤中完成的两项任务的描述以用于报告目的。所以这是评论:
STEP_6 JRTB-5:添加了订阅群组的功能 JRTB-6:添加了查看群组订阅列表的功能。
这导致了 47 个文件的更改...这是一个很大的变化。虽然你无法从功能描述中看出。毕竟,要了解完整的深度,您需要知道您需要为 API 编写 Java 客户端,本质上是更新整个应用程序。事情就是这样,在服务器上工作 - 有很多工作,但客户端的可见性很小...)) 朋友,我传统上为您提供一种对我的工作表现出兴趣的方法 - 订阅github帐户,加入电报频道并写下有关文章的问题,如果有不清楚的地方! 以下是拉取请求的链接,其中包含此STEP_6的更改。感谢大家的阅读。更多内容即将推出 - 让我们讨论一下删除订阅、停用配置文件等等。不要切换))
GO TO FULL VERSION