Бәріңе сәлем! Өткен аптада бастаған тапсырмамызбен жұмысты жалғастырамыз .
Біз JRTB-5 енгіземіз
Енді JavaRush мақалаларының кейбір тобына жазылу үшін пәрменді қосу керек. Бұны қалай істейді? Біз мен ойлап тапқан ең қарапайым сценарийді ұстанамыз. Бізде топ идентификаторы арқылы кіру мүмкіндігі болғандықтан, оны тасымалдау үшін бізге пайдаланушы қажет. Ол үшін пайдаланушы /addGroupSub GROUP_ID пәрменін енгізеді, ол екі жолдың бірімен жұмыс істейді: пәрменнің өзі ғана келсе: /addGroupSub , жауап ретінде барлық топтардың тізімі және олардың идентификаторлары жіберіледі. Содан кейін пайдаланушы өзіне қажет топ идентификаторын таңдай алады және осы пәрменде сұраудың екінші нұсқасын жасай алады: /addGroupSub GROUP_ID - содан кейін осы пайдаланушымен осы топтың жазбасы болады. Менің ойымша, біз болашақта жақсы жұмыс істей аламыз. Біздің мақсатымыз - керемет қолданушы тәжірибесін емес, дамуды көрсету (айтуға ұяламын, бірақ мен орыс тілінде мұны білдіретін терминді білмеймін). Бүкіл қолданба арқылы өтетін функционалдылықты дұрыс қосу үшін (біздің жағдайда, телеграмма бот клиентінен дерекқорға дейін) сіз бір жерден бастауыңыз керек. Біз мұны дерекқор жағынан жасаймыз.Дерекқорға жаңа тасымалдауды қосу
Бірінші істеу керек - жаңа дерекқорды тасымалдауды және JR-де пайдаланушылар тобының жазылу деректерін сақтау мүмкіндігін қосу. Бұл қалай болуы керек екенін есте сақтау үшін « Жобаны жоспарлау: жеті рет өлшеңіз » мақаласына оралыңыз . Екінші фотода дерекқордың шамамен диаграммасы бар. Топ ақпаратын сақтау үшін бізге кесте қосу керек:- JavaRush ішіндегі топ идентификаторы да біздің идентификаторымыз болады. Біз оларға сенеміз және бұл идентификаторлардың бірегей екеніне сенеміз;
- тақырып - біздің суреттерімізде бұл атау болды - топтың бейресми атауы; яғни JavaRush веб-сайтында көретініміз;
- last_article_id - бұл қызықты өріс. Ол осы топтағы мақаланың соңғы идентификаторын сақтайды, оны бот өз жазылушыларына жіберген. Осы өрісті пайдалану арқылы жаңа мақалаларды іздеу механизмі жұмыс істейді. Жаңа жазылушылар пайдаланушы жазылғанға дейін жарияланған мақалаларды алмайды: тек топқа жазылғаннан кейін жарияланған мақалалар.
V00002__created_groupsub_many_to_many.sql:
-- add PRIMARY KEY FOR tg_user
ALTER TABLE tg_user ADD PRIMARY KEY (chat_id);
-- ensure that the tables with these names are removed before creating a new one.
DROP TABLE IF EXISTS group_sub;
DROP TABLE IF EXISTS group_x_user;
CREATE TABLE group_sub (
id INT,
title VARCHAR(100),
last_article_id INT,
PRIMARY KEY (id)
);
CREATE TABLE group_x_user (
group_sub_id INT NOT NULL,
user_id VARCHAR(100) NOT NULL,
FOREIGN KEY (user_id) REFERENCES tg_user(chat_id),
FOREIGN KEY (group_sub_id) REFERENCES group_sub(id),
UNIQUE(user_id, group_sub_id)
);
Айта кету керек, алдымен мен ескі кестені өзгертемін - оған бастапқы кілт қосамын. Мен мұны сол кезде қандай да бір түрде жіберіп алдым, бірақ қазір MySQL маған gorup_x_user кестесіне ШЕТЕЛДІК КІЛТ қосу мүмкіндігін бермеді және осы тасымалдаудың бөлігі ретінде мен дерекқорды жаңарттым. Маңызды аспектіні ескеріңіз. Дерекқорды өзгерту дәл осылай жасалуы керек - қажет нәрсенің бәрі жаңа тасымалдауда, бірақ бұрыннан шығарылған тасымалдауды жаңарту арқылы емес. Иә, біздің жағдайда ештеңе болмас еді, өйткені бұл сынақ жобасы және біз оның тек бір жерде орналастырылғанын білеміз, бірақ бұл дұрыс емес тәсіл болар еді. Бірақ біз бәрі дұрыс болғанын қалаймыз. Содан кейін кестелерді жасамас бұрын жою керек. Бұл не үшін? Егер кездейсоқ дерекқорда осындай атаулары бар кестелер болса, көшіру сәтсіз аяқталмайды және күткендей жұмыс істейді. Содан кейін біз екі кестені қосамыз. Барлығы біз қалағандай болды. Енді біз қолданбамызды іске қосуымыз керек. Егер бәрі басталып, үзілмесе, көшу жазылады. Ал мұны екі рет тексеру үшін мәліметтер базасына барамыз: а) мұндай кестелер пайда болғанына; б) ұшу жолының техникалық кестесінде жаңа жазба бар. Бұл көшіру жұмысын аяқтайды, репозитарийлерге көшейік.
Репозиторий қабатын қосу
Spring Boot деректерінің арқасында мұнда бәрі өте қарапайым: бізге GroupSub нысанын қосу керек, TelegramUser қолданбасын сәл жаңарту және бос дерлік GroupSubRepository қосу керек: GroupSub нысанын TelegramUser сияқты пакетке қосамыз:package com.github.javarushcommunity.jrtb.repository.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.isNull;
@Data
@Entity
@Table(name = "group_sub")
@EqualsAndHashCode
public class GroupSub {
@Id
private Integer id;
@Column(name = "title")
private String title;
@Column(name = "last_article_id")
private Integer lastArticleId;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "group_x_user",
joinColumns = @JoinColumn(name = "group_sub_id"),
inverseJoinColumns = @JoinColumn(name = "user_id")
)
private List<TelegramUser> users;
public void addUser(TelegramUser telegramUser) {
if (isNull(users)) {
users = new ArrayList<>();
}
users.add(telegramUser);
}
}
Айта кету керек, бізде топқа жазылған барлық пайдаланушылар жиынтығын қамтитын қосымша пайдаланушылар өрісі бар. Және екі annotation - ManyToMany және JoinTable - бұл бізге қажет нәрсе. Сол өрісті TelegramUser үшін қосу керек:
@ManyToMany(mappedBy = "users", fetch = FetchType.EAGER)
private List<GroupSub> groupSubs;
Бұл өріс GroupSub нысанында жазылған біріктірулерді пайдаланады. Және, шын мәнінде, GroupSub үшін біздің репозиторий класы GroupSubRepository болып табылады :
package com.github.javarushcommunity.jrtb.repository;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* {@link Repository} for {@link GroupSub} entity.
*/
@Repository
public interface GroupSubRepository extends JpaRepository<GroupSub, Integer> {
}
Бұл кезеңде бізге қосымша әдістер қажет емес: JpaRepository ата-бабасында іске асырылғандар бізге жеткілікті. TelegramUserRepositoryIT жүйесінде біздің көптен көпке жұмыс істейтінін тексеретін сынақ жазайық. Сынақтың идеясы - біз sql сценарийі арқылы дерекқорға әр пайдаланушыға жазылымдардың 5 тобын қосамыз, осы пайдаланушыны оның идентификаторы бойынша аламыз және дәл сол топтарды және дәл сол мәндерді алғанымызды тексереміз. Бұны қалай істейді? Есептегішті деректерге енгізуге болады, содан кейін біз оны тексеріп, тексере аламыз. Міне FiveGroupSubsForUser.sql сценарийі:
INSERT INTO tg_user VALUES (1, 1);
INSERT INTO group_sub VALUES
(1, 'g1', 1),
(2, 'g2', 2),
(3, 'g3', 3),
(4, 'g4', 4),
(5, 'g5', 5);
INSERT INTO group_x_user VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1);
Ал сынақтың өзі:
@Sql(scripts = {"/sql/clearDbs.sql", "/sql/fiveGroupSubsForUser.sql"})
@Test
public void shouldProperlyGetAllGroupSubsForUser() {
//when
Optional<TelegramUser> userFromDB = telegramUserRepository.findById("1");
//then
Assertions.assertTrue(userFromDB.isPresent());
List<GroupSub> groupSubs = userFromDB.get().getGroupSubs();
for (int i = 0; i < groupSubs.size(); i++) {
Assertions.assertEquals(String.format("g%s", (i + 1)), groupSubs.get(i).getTitle());
Assertions.assertEquals(i + 1, groupSubs.get(i).getId());
Assertions.assertEquals(i + 1, groupSubs.get(i).getLastArticleId());
}
}
Енді GroupSub нысаны үшін бірдей мағынадағы сынақты қосамыз. Ол үшін groupSubRepositoryIT сияқты пакетте groupSubRepositoryIT сынақ сыныбын жасайық :
package com.github.javarushcommunity.jrtb.repository;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;
import java.util.List;
import java.util.Optional;
import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE;
/**
* Integration-level testing for {@link GroupSubRepository}.
*/
@ActiveProfiles("test")
@DataJpaTest
@AutoConfigureTestDatabase(replace = NONE)
public class GroupSubRepositoryIT {
@Autowired
private GroupSubRepository groupSubRepository;
@Sql(scripts = {"/sql/clearDbs.sql", "/sql/fiveUsersForGroupSub.sql"})
@Test
public void shouldProperlyGetAllUsersForGroupSub() {
//when
Optional<GroupSub> groupSubFromDB = groupSubRepository.findById(1);
//then
Assertions.assertTrue(groupSubFromDB.isPresent());
Assertions.assertEquals(1, groupSubFromDB.get().getId());
List<TelegramUser> users = groupSubFromDB.get().getUsers();
for(int i=0; i<users.size(); i++) {
Assertions.assertEquals(String.valueOf(i + 1), users.get(i).getChatId());
Assertions.assertTrue(users.get(i).isActive());
}
}
}
Және жетіспейтін бесUsersForGroupSub.sql сценарийі:
INSERT INTO tg_user VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1);
INSERT INTO group_sub VALUES (1, 'g1', 1);
INSERT INTO group_x_user VALUES
(1, 1),
(1, 2),
(1, 3),
(1, 4),
(1, 5);
Осы кезде репозиториймен жұмыстың бір бөлігін аяқталды деп санауға болады. Енді қызмет көрсету деңгейін жазайық.
Біз GroupSubService жазамыз
Бұл кезеңде жазылымдар топтарымен жұмыс істеу үшін біз тек оларды сақтай білуіміз керек, сондықтан ешқандай проблема жоқ: біз GroupSubService қызметін жасаймыз және оның GroupSubServiceImpl іске асыруы басқа қызметтерді қамтитын пакетте - сервис:package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
/**
* Service for manipulating with {@link GroupSub}.
*/
public interface GroupSubService {
GroupSub save(String chatId, GroupDiscussionInfo groupDiscussionInfo);
}
Және оны жүзеге асыру:
package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.repository.GroupSubRepository;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.ws.rs.NotFoundException;
import java.util.Optional;
@Service
public class GroupSubServiceImpl implements GroupSubService {
private final GroupSubRepository groupSubRepository;
private final TelegramUserService telegramUserService;
@Autowired
public GroupSubServiceImpl(GroupSubRepository groupSubRepository, TelegramUserService telegramUserService) {
this.groupSubRepository = groupSubRepository;
this.telegramUserService = telegramUserService;
}
@Override
public GroupSub save(String chatId, GroupDiscussionInfo groupDiscussionInfo) {
TelegramUser telegramUser = telegramUserService.findByChatId(chatId).orElseThrow(NotFoundException::new);
//TODO add exception handling
GroupSub groupSub;
Optional<GroupSub> groupSubFromDB = groupSubRepository.findById(groupDiscussionInfo.getId());
if(groupSubFromDB.isPresent()) {
groupSub = groupSubFromDB.get();
Optional<TelegramUser> first = groupSub.getUsers().stream()
.filter(it -> it.getChatId().equalsIgnoreCase(chatId))
.findFirst();
if(first.isEmpty()) {
groupSub.addUser(telegramUser);
}
} else {
groupSub = new GroupSub();
groupSub.addUser(telegramUser);
groupSub.setId(groupDiscussionInfo.getId());
groupSub.setTitle(groupDiscussionInfo.getTitle());
}
return groupSubRepository.save(groupSub);
}
}
Spring Data дұрыс жұмыс істеуі және көптен көпке жазба жасалуы үшін біз жасап жатқан жазылым тобына арналған дерекқорымыздан пайдаланушыны алып, GroupSub нысанына қосуымыз керек. Осылайша, біз бұл жазылымды сақтауға тасымалдаған кезде, group_x_user кестесі арқылы да қосылым жасалады. Мұндай жазылым тобы бұрыннан жасалған жағдай болуы мүмкін және оған басқа пайдаланушы қосу керек. Ол үшін алдымен деректер қорынан топ идентификаторын аламыз, егер жазба болса онымен жұмыс істейміз, жоқ болса жаңасын жасаймыз. TelegramUser-пен жұмыс істеу үшін біз TelegramUserService қызметін SOLID қағидаларының соңғысын ұстанатынымызды ескеру маңызды. Қазіргі уақытта идентификатор бойынша жазба табылмаса, мен жай ғана ерекшелік жіберемін. Ол қазір ешқандай жолмен өңделмейді: біз мұны ең соңында, MVP алдында жасаймыз. GroupSubServiceTest сыныбы үшін екі бірлік сынақтарын жазайық . Бізге қайсысы керек? Сақтау әдісі GroupSubRepository-де шақырылатынына және бір пайдаланушысы бар нысан GroupSub-қа жіберілетініне сенімді болғым келеді - ол берілген идентификаторды пайдаланып бізге TelegramUserService қайтарады. Ал екінші опция, сол идентификаторы бар топ дерекқорда бұрыннан бар болса және бұл топтың бір пайдаланушысы болса және осы топқа басқа пайдаланушы қосылатынын және бұл нысан сақталатынын тексеру керек. Міне, іске асыру:
package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.repository.GroupSubRepository;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.Optional;
@DisplayName("Unit-level testing for GroupSubService")
public class GroupSubServiceTest {
private GroupSubService groupSubService;
private GroupSubRepository groupSubRepository;
private TelegramUser newUser;
private final static String CHAT_ID = "1";
@BeforeEach
public void init() {
TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);
groupSubRepository = Mockito.mock(GroupSubRepository.class);
groupSubService = new GroupSubServiceImpl(groupSubRepository, telegramUserService);
newUser = new TelegramUser();
newUser.setActive(true);
newUser.setChatId(CHAT_ID);
Mockito.when(telegramUserService.findByChatId(CHAT_ID)).thenReturn(Optional.of(newUser));
}
@Test
public void shouldProperlySaveGroup() {
//given
GroupDiscussionInfo groupDiscussionInfo = new GroupDiscussionInfo();
groupDiscussionInfo.setId(1);
groupDiscussionInfo.setTitle("g1");
GroupSub expectedGroupSub = new GroupSub();
expectedGroupSub.setId(groupDiscussionInfo.getId());
expectedGroupSub.setTitle(groupDiscussionInfo.getTitle());
expectedGroupSub.addUser(newUser);
//when
groupSubService.save(CHAT_ID, groupDiscussionInfo);
//then
Mockito.verify(groupSubRepository).save(expectedGroupSub);
}
@Test
public void shouldProperlyAddUserToExistingGroup() {
//given
TelegramUser oldTelegramUser = new TelegramUser();
oldTelegramUser.setChatId("2");
oldTelegramUser.setActive(true);
GroupDiscussionInfo groupDiscussionInfo = new GroupDiscussionInfo();
groupDiscussionInfo.setId(1);
groupDiscussionInfo.setTitle("g1");
GroupSub groupFromDB = new GroupSub();
groupFromDB.setId(groupDiscussionInfo.getId());
groupFromDB.setTitle(groupDiscussionInfo.getTitle());
groupFromDB.addUser(oldTelegramUser);
Mockito.when(groupSubRepository.findById(groupDiscussionInfo.getId())).thenReturn(Optional.of(groupFromDB));
GroupSub expectedGroupSub = new GroupSub();
expectedGroupSub.setId(groupDiscussionInfo.getId());
expectedGroupSub.setTitle(groupDiscussionInfo.getTitle());
expectedGroupSub.addUser(oldTelegramUser);
expectedGroupSub.addUser(newUser);
//when
groupSubService.save(CHAT_ID, groupDiscussionInfo);
//then
Mockito.verify(groupSubRepository).findById(groupDiscussionInfo.getId());
Mockito.verify(groupSubRepository).save(expectedGroupSub);
}
}
Мен init() әдісін BeforeEach annotationсымен қостым . Осылайша, олар әдетте әрбір сынақ орындалмас бұрын орындалатын әдісті жасайды және оған барлық сынақтар үшін жалпы логиканы қоюға болады. Біздің жағдайда TelegramUserService қызметін осы сыныптың барлық сынақтары үшін бірдей құлыптауымыз керек, сондықтан бұл логиканы жалпы әдіске көшіру мағынасы бар. Мұнда екі мокито дизайны қолданылады:
-
Mockito.when(o1.m1(a1)).thenReturn(o2) - онда a1 аргументі бар o1 нысанында m1 әдісі шақырылғанда , әдіс o2 нысанын қайтаратынын айтамыз . Бұл мокитоның ең маңызды функционалдығы дерлік - жалған нысанды бізге қажет нәрсені қайтаруға мәжбүрлеу;
-
Mockito.verify(o1).m1(a1) - m1 әдісі a1 аргументі арқылы o1 нысанында шақырылғанын тексереді . Әрине, сақтау әдісінің қайтарылған нысанын пайдалану мүмкін болды, бірақ мен басқа ықтимал әдісті көрсету арқылы оны біршама күрделендіруді шештім. Қашан пайдалы болуы мүмкін? Жалған сабақтардың әдістері жарамсыз болып табылатын жағдайларда. Сонда Mockito.verify болмаса жұмыс болмайды)))
/addGroupSub пәрменін жасаңыз
Мұнда біз келесі логиканы орындауымыз керек: егер біз ешқандай контекстсіз жай ғана пәрменді алсақ, біз пайдаланушыға көмектесеміз және оған қажетті ақпаратты ботқа бере алуы үшін идентификаторлары бар барлық топтардың тізімін береміз. Ал егер пайдаланушы басқа сөз(дер) арқылы ботқа пәрмен жіберсе, сол идентификаторы бар топты табыңыз немесе ондай топ жоқ деп жазыңыз. Біздің атауымызға жаңа мән қосайық - CommandName:ADD_GROUP_SUB("/addgroupsub")
Дерекқордан әрі қарай телеграмма ботына көшейік - пәрмендер бумасында AddGroupSubCommand сыныбын жасаңыз:
package com.github.javarushcommunity.jrtb.command;
import com.github.javarushcommunity.jrtb.javarushclient.JavaRushGroupClient;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupDiscussionInfo;
import com.github.javarushcommunity.jrtb.javarushclient.dto.GroupRequestArgs;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.service.GroupSubService;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.stream.Collectors;
import static com.github.javarushcommunity.jrtb.command.CommandName.ADD_GROUP_SUB;
import static com.github.javarushcommunity.jrtb.command.CommandUtils.getChatId;
import static com.github.javarushcommunity.jrtb.command.CommandUtils.getMessage;
import static java.util.Objects.isNull;
import static org.apache.commons.lang3.StringUtils.SPACE;
import static org.apache.commons.lang3.StringUtils.isNumeric;
/**
* Add Group subscription {@link Command}.
*/
public class AddGroupSubCommand implements Command {
private final SendBotMessageService sendBotMessageService;
private final JavaRushGroupClient javaRushGroupClient;
private final GroupSubService groupSubService;
public AddGroupSubCommand(SendBotMessageService sendBotMessageService, JavaRushGroupClient javaRushGroupClient,
GroupSubService groupSubService) {
this.sendBotMessageService = sendBotMessageService;
this.javaRushGroupClient = javaRushGroupClient;
this.groupSubService = groupSubService;
}
@Override
public void execute(Update update) {
if (getMessage(update).equalsIgnoreCase(ADD_GROUP_SUB.getCommandName())) {
sendGroupIdList(getChatId(update));
return;
}
String groupId = getMessage(update).split(SPACE)[1];
String chatId = getChatId(update);
if (isNumeric(groupId)) {
GroupDiscussionInfo groupById = javaRushGroupClient.getGroupById(Integer.parseInt(groupId));
if (isNull(groupById.getId())) {
sendGroupNotFound(chatId, groupId);
}
GroupSub savedGroupSub = groupSubService.save(chatId, groupById);
sendBotMessageService.sendMessage(chatId, "Подписал на группу " + savedGroupSub.getTitle());
} else {
sendGroupNotFound(chatId, groupId);
}
}
private void sendGroupNotFound(String chatId, String groupId) {
String groupNotFoundMessage = "Нет группы с ID = \"%s\"";
sendBotMessageService.sendMessage(chatId, String.format(groupNotFoundMessage, groupId));
}
private void sendGroupIdList(String chatId) {
String groupIds = javaRushGroupClient.getGroupList(GroupRequestArgs.builder().build()).stream()
.map(group -> String.format("%s - %s \n", group.getTitle(), group.getId()))
.collect(Collectors.joining());
String message = "Whatбы подписаться на группу - передай комадну вместе с ID группы. \n" +
"Например: /addGroupSub 16. \n\n" +
"я подготовил список всех групп - выберай Howую хочешь :) \n\n" +
"Name группы - ID группы \n\n" +
"%s";
sendBotMessageService.sendMessage(chatId, String.format(message, groupIds));
}
}
Бұл сынып apache-commons кітапханасындағы isNumeric әдісін пайдаланады , сондықтан оны жадымызға қосамыз:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache.commons.version}</version>
</dependency>
Ал қасиеттер блогында:
<apache.commons.version>3.11</apache.commons.version>
Бұл логиканың барлығы сыныпта. Оны мұқият оқып шығыңыз. Егер сізде сұрақтар/ұсыныстар болса, оларды түсініктемелерде жазыңыз. Осыдан кейін біз командалық картамыздағы CommandContainer пәрменін қосуымыз керек:
.put(ADD_GROUP_SUB.getCommandName(), new AddGroupSubCommand(sendBotMessageService, javaRushGroupClient, groupSubService))
Және бәрі осы команда үшін. Мен бұл функцияны қандай да бір түрде тексергім келеді, бірақ әзірге мен оны дерекқорда шынымен қарай аламын. Үшінші бөлімде мен JRTB-6 өзгерістерін қосамын, осылайша біз пайдаланушы жазылған топтардың тізімін көре аламыз. Енді осының бәрін тексеріп көрсек жақсы болар еді. Ол үшін біз Telegram-да барлық әрекеттерді орындап, дерекқорда тексереміз. Тесттерді жазғандықтан, бәрі жақсы болуы керек. Мақала өте ұзақ, сондықтан біз кейінірек AddGroupSubCommand үшін сынақ жазамыз және ұмытып кетпеу үшін codeқа TODO қосамыз.
GO TO FULL VERSION