JavaRush /جاوا بلاگ /Random-SD /اسان مضمونن جي هڪ گروپ ۾ رڪنيت حاصل ڪرڻ جي صلاحيت شامل ڪر...

اسان مضمونن جي هڪ گروپ ۾ رڪنيت حاصل ڪرڻ جي صلاحيت شامل ڪري رهيا آهيون. (حصو 2) - "جاوا پروجيڪٽ A کان Z تائين"

گروپ ۾ شايع ٿيل
هيلو سڀ! اسان ڪم تي ڪم جاري رکون ٿا جيڪو اسان گذريل هفتي شروع ڪيو ."جاوا پروجيڪٽ A کان Z تائين": مضمونن جي گروپ ۾ رڪنيت حاصل ڪرڻ جي صلاحيت شامل ڪرڻ.  حصو 2 - 1

اسان JRTB-5 لاڳو ڪندا آهيون

ھاڻي اسان کي ھڪڙي حڪم شامل ڪرڻ جي ضرورت آھي ته جيئن اسان جاوا رش کان مضمونن جي ڪجھ گروپ جي رڪنيت حاصل ڪري سگھون. اهو ڪيئن ڪجي؟ اسان سڀ کان سادو منظر جي پيروي ڪنداسين جنهن سان آئون آيو آهيان. جيئن ته اسان وٽ گروپ ID ذريعي رسائي آهي، اسان کي صارف کي ان کي منتقل ڪرڻ جي ضرورت آهي. هن کي ڪرڻ لاءِ، استعمال ڪندڙ ڪمانڊ داخل ڪندو /addGroupSub GROUP_ID، جيڪو ڪم ڪندو ٻن طريقن مان: جيڪڏهن صرف ڪمانڊ پاڻ اچي: /addGroupSub ، سڀني گروپن جي لسٽ ۽ انهن جي سڃاڻپ جواب ۾ موڪلي ويندي. پوءِ استعمال ڪندڙ گروپ ID چونڊڻ جي قابل هوندو جنهن جي هن کي ضرورت آهي ۽ هن حڪم ۾ درخواست جو ٻيو نسخو ٺاهي: /addGroupSub GROUP_ID - ۽ پوءِ هن صارف وٽ هن گروپ جو رڪارڊ هوندو. منهنجو خيال آهي ته اسان مستقبل ۾ بهتر ڪري سگهون ٿا. اسان جو مقصد ترقي کي ڏيکارڻ آهي، ۽ نه سپر ٿڌو صارف تجربو (مان چوڻ ۾ شرمسار آهيان، پر مون کي خبر ناهي ته روسي ۾ اصطلاح جنهن جو مطلب هي هوندو). ڪارڪردگي کي صحيح طور تي شامل ڪرڻ لاءِ جيڪا پوري ايپليڪيشن ذريعي وڃي ٿي (اسان جي صورت ۾ ، ٽيليگرام بوٽ ڪلائنٽ کان ڊيٽابيس تائين) ، توهان کي ڪجهه آخر ۾ شروع ڪرڻ جي ضرورت آهي. اسان هن کي ڊيٽابيس جي پاسي کان ڪنداسين.

ڊيٽابيس ۾ نئين لڏپلاڻ شامل ڪرڻ

ڪرڻ جي پهرين شيء هڪ نئين ڊيٽابيس لڏپلاڻ ۽ JR ۾ صارف گروپ سبسڪرپشن ڊيٽا محفوظ ڪرڻ جي صلاحيت شامل ڪرڻ آهي. ياد رکڻ لاءِ ته اهو ڪيئن هئڻ گهرجي، مضمون ڏانهن واپس وڃو ” پروجيڪٽ پلاننگ: ماپ ست ڀيرا “. اتي ٻئي تصوير ۾ ڊيٽابيس جي هڪ اندازي مطابق ڊراگرام آهي. گروپ جي معلومات کي ذخيرو ڪرڻ لاء اسان کي ٽيبل شامل ڪرڻو پوندو:
  • JavaRush ۾ گروپ جي ID به اسان جي ID هوندي. اسان انهن تي ڀروسو ڪريون ٿا ۽ يقين رکون ٿا ته اهي IDs منفرد آهن؛
  • عنوان - اسان جي تصويرن ۾ اهو نالو هو - گروپ جو غير رسمي نالو؛ اھو آھي، جيڪو اسان JavaRush ويب سائيٽ تي ڏسون ٿا؛
  • last_article_id - ۽ هي هڪ دلچسپ ميدان آهي. اهو هن گروپ ۾ آرٽيڪل جي آخري 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 مون کي FOREIGN KEY شامل ڪرڻ جو موقعو نه ڏنو gorup_x_user ٽيبل لاءِ، ۽ هن لڏپلاڻ جي حصي طور مون ڊيٽابيس کي اپڊيٽ ڪيو. مهرباني ڪري هڪ اهم پاسو نوٽ ڪريو. ڊيٽابيس کي تبديل ڪرڻ بلڪل هن طريقي سان ٿيڻ گهرجي - هر شيء جيڪا گهربل آهي نئين لڏپلاڻ ۾، پر اڳ ۾ ئي جاري ٿيل لڏپلاڻ کي اپڊيٽ ڪرڻ سان نه. ها، اسان جي صورت ۾ ڪجھ به نه ٿيندو، ڇو ته هي هڪ آزمائشي منصوبو آهي ۽ اسان ڄاڻون ٿا ته اهو صرف هڪ جڳهه تي لڳايو ويو آهي، پر اهو غلط طريقو هوندو. پر اسان چاهيون ٿا ته سڀ ڪجهه صحيح هجي. اڳيان اچي ٿو انهن کي ٺاهڻ کان پهريان ٽيبل کي حذف ڪرڻ. ائين ڇو آهي؟ انهي ڪري ته جيڪڏهن ڪنهن اتفاق سان ڊيٽابيس ۾ اهڙن نالن سان جدول موجود هئا، لڏپلاڻ ناڪام نه ٿيندي ۽ بلڪل توقع وانگر ڪم ڪندو. ۽ پوء اسان ٻه ٽيبل شامل ڪندا آهيون. سڀ ڪجهه ائين هو جيئن اسان چاهيون ٿا. هاڻي اسان کي اسان جي اپليڪيشن شروع ڪرڻ جي ضرورت آهي. جيڪڏهن سڀ ڪجهه شروع ٿئي ٿو ۽ نه ڀڃي، پوء لڏپلاڻ رڪارڊ ٿيل آهي. ۽ ان کي ٻه ڀيرا چيڪ ڪرڻ لاءِ، اسان ڊيٽابيس ڏانهن وڃون ٿا ته پڪ ڪرڻ لاءِ ته: الف) اهڙيون ٽيبلون ظاهر ٿيون آهن؛ ب) فلائي وي ٽيڪنيڪل ٽيبل ۾ هڪ نئين داخلا آهي. هي لڏپلاڻ وارو ڪم مڪمل ڪري ٿو، اچو ته مخزن ڏانهن وڃو.

مخزن جي پرت کي شامل ڪرڻ

اسپرنگ بوٽ ڊيٽا جي مهرباني، هتي سڀ ڪجهه بلڪل سادو آهي: اسان کي 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);
   }
}
هڪ ڳالهه نوٽ ڪرڻ جي قابل آهي ته اسان وٽ هڪ اضافي استعمال ڪندڙ فيلڊ آهي جنهن ۾ سڀني صارفين جو هڪ مجموعو هوندو جيڪو گروپ ۾ رڪنيت حاصل ڪيو ويو آهي. ۽ ٻه تشريحون - ManyToMany ۽ JoinTable - بلڪل اهي آهن جيڪي اسان کي هن جي ضرورت آهي. ٽيليگرام استعمال ڪندڙ لاءِ ساڳيو فيلڊ شامل ڪرڻ جي ضرورت آهي:
@ManyToMany(mappedBy = "users", fetch = FetchType.EAGER)
private List<GroupSub> groupSubs;
ھي فيلڊ استعمال ڪري ٿو جوائن جو لکيل آھي GroupSub entity ۾. ۽، حقيقت ۾، گروپسب لاءِ اسان جو مخزن وارو طبقو آهي 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 گروپ شامل ڪنداسين، هن صارف کي هن جي ID ذريعي حاصل ڪريو ۽ چيڪ ڪريو ته اسان کي اهي گروپ مليا آهن ۽ بلڪل ساڳين قدرن سان. اهو ڪيئن ڪجي؟ توهان ڊيٽا ۾ هڪ ڪائونٽر داخل ڪري سگهو ٿا، جنهن کي اسين پوءِ وڃو ۽ چيڪ ڪري سگهون ٿا. ھتي آھي 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 entity لاءِ. ائين ڪرڻ لاء، اچو ته هڪ ٽيسٽ ڪلاس گروپSubRepositoryIT ساڳي پيڪيج ۾ ٺاهيون جيئن 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());
       }
   }
}
۽ غائب FiveUsersForGroupSub.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 لکندا آهيون

هن مرحلي تي، رڪنيتن جي گروپن سان ڪم ڪرڻ لاءِ، اسان کي صرف انهن کي محفوظ ڪرڻ جي ضرورت آهي، تنهن ڪري ڪو مسئلو ناهي: اسان هڪ پيڪيج ۾ GroupSubServiceImpl جي GroupSubService سروس ۽ ان تي عمل درآمد ڪريون ٿا جنهن ۾ ٻيون خدمتون شامل آهن - خدمت:
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);
   }
}
اسپرنگ ڊيٽا کي صحيح طريقي سان ڪم ڪرڻ لاءِ ۽ هڪ کان وڌيڪ رڪارڊ ٺاهڻ لاءِ، اسان کي صارف کي اسان جي ڊيٽابيس مان حاصل ڪرڻ جي ضرورت آهي سبسڪرپشن گروپ لاءِ جيڪو اسان ٺاهي رهيا آهيون ۽ ان کي GroupSub اعتراض ۾ شامل ڪريون. اهڙيء طرح، جڏهن اسان هن رڪنيت کي محفوظ ڪرڻ لاء منتقل ڪندا آهيون، هڪ ڪنيڪشن پڻ ٺاهي ويندي گروپ_x_user ٽيبل ذريعي. ٿي سگهي ٿو هڪ اهڙي صورتحال جڏهن اهڙي سبسڪرپشن گروپ ٺاهي وئي هجي ۽ توهان کي صرف ان ۾ هڪ ٻيو صارف شامل ڪرڻو پوندو. هن کي ڪرڻ لاء، اسان پهريان ڊيٽابيس مان گروپ جي سڃاڻپ حاصل ڪندا آهيون، ۽ جيڪڏهن ڪو رڪارڊ آهي، اسان ان سان ڪم ڪريون ٿا، جيڪڏهن نه، اسان هڪ نئين ٺاهيندا آهيون. اهو نوٽ ڪرڻ ضروري آهي ته TelegramUser سان ڪم ڪرڻ لاءِ اسان استعمال ڪريون ٿا TelegramUserService جي آخري SOLID اصولن تي عمل ڪرڻ لاءِ. هن وقت، جيڪڏهن اسان کي ID طرفان رڪارڊ نه ملي، مان صرف هڪ استثنا اڇلائيندس. اهو هاڻي ڪنهن به طريقي سان عمل نه ڪيو پيو وڃي: اسان هن کي آخر ۾ ڪنداسين، ايم وي پي کان اڳ. اچو ته GroupSubServiceTest ڪلاس لاءِ ٻه يونٽ ٽيسٽ لکون . اسان کي ڪهڙي ضرورت آهي؟ مان پڪ ڪرڻ چاهيان ٿو ته محفوظ ڪرڻ جو طريقو GroupSubRepository ۾ سڏيو ويندو ۽ هڪ واحد صارف سان هڪ ادارو GroupSub ڏانهن منتقل ڪيو ويندو - اهو جيڪو اسان کي ڏنل ID استعمال ڪندي TelegramUserService واپس ڪندو. ۽ ٻيو آپشن، جڏهن هڪ گروپ جي ساڳي ID سان گڏ ڊيٽابيس ۾ اڳ ۾ ئي آهي ۽ هن گروپ ۾ اڳ ۾ ئي هڪ صارف آهي، ۽ توهان کي چيڪ ڪرڻ جي ضرورت آهي ته ٻيو صارف هن گروپ ۾ شامل ڪيو ويندو ۽ هي اعتراض محفوظ ڪيو ويندو. هتي عمل درآمد آهي:
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 تشريح سان. هن طريقي سان، اهي عام طور تي هڪ طريقو ٺاهيندا آهن جيڪي هر ٽيسٽ هلائڻ کان اڳ عمل ۾ ايندا، ۽ اهو ممڪن آهي ته ان ۾ سڀني تجربن لاء عام منطق شامل ڪيو وڃي. اسان جي حالت ۾، اسان کي لازمي طور تي بند ڪرڻ جي ضرورت آهي TelegramUserService هن طبقي جي سڀني ٽيسٽن لاء، تنهنڪري هن منطق کي عام طريقي سان منتقل ڪرڻ جو احساس آهي. هتي ٻه mokito ڊيزائن استعمال ڪيا ويا آهن:
  • Mockito.when(o1.m1(a1)).ThenReturn(o2) - ان ۾ اسان چئون ٿا ته جڏهن ميٿڊ m1 سڏيو ويندو آهي اعتراض o1 تي آرگيومينٽ a1 سان ، طريقو واپس ڪندو اعتراض o2 . اها تقريبن سڀ کان اهم ڪارڪردگي آهي موڪيٽو - ٺٺولي اعتراض کي واپس ڪرڻ لاءِ مجبور ڪرڻ لاءِ جيڪو اسان کي گهربل آهي؛

  • Mockito.verify(o1).m1(a1) - جيڪو انهي طريقي جي تصديق ڪري ٿو m1 اعتراض o1 تي دليل a1 سان سڏيو ويو . اهو ممڪن هو، يقينا، محفوظ طريقي جي واپسي اعتراض کي استعمال ڪرڻ لاء، پر مون ان کي ٿورو وڌيڪ پيچيده ڪرڻ جو فيصلو ڪيو ٻيو ممڪن طريقو ڏيکاريندي. جڏهن اهو مفيد ٿي سگهي ٿو؟ ڪيسن ۾ جتي ٺٺوليون طبقن جا طريقا باطل موٽندا آهن. پوءِ Mockito.verify کان سواءِ ڪو ڪم نه ٿيندو)))

اسان انهي خيال تي عمل جاري رکون ٿا ته ٽيسٽ لکڻ جي ضرورت آهي، ۽ انهن مان گهڻو ڪجهه لکڻ جي ضرورت آهي. ايندڙ اسٽيج ٽيليگرام بوٽ ٽيم سان ڪم ڪري رهيو آهي.

ڪمانڊ ٺاهيو /addGroupSub

هتي اسان کي هيٺين منطق کي انجام ڏيڻ جي ضرورت آهي: جيڪڏهن اسان کي صرف هڪ حڪم ملي ٿو، بغير ڪنهن حوالي جي، اسان صارف جي مدد ڪريون ٿا ۽ کيس سڀني گروپن جي هڪ فهرست ڏيون ٿا انهن جي سڃاڻپ سان ته جيئن هو بوٽ کي ضروري معلومات منتقل ڪري سگهي. ۽ جيڪڏهن صارف ڪنهن ٻئي لفظ سان بوٽ ڏانهن هڪ حڪم موڪلي ٿو، انهي ID سان هڪ گروپ ڳوليو يا لکو ته اهڙو ڪو گروپ ناهي. اچو ته اسان جي نالي ۾ هڪ نئين قيمت شامل ڪريو - 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));
   }
}
هي ڪلاس استعمال ڪري ٿو isNumeric طريقو apache-commons لائبريري مان، تنهنڪري اچو ته ان کي پنهنجي ياداشت ۾ شامل ڪريون:
<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 مان تبديليون شامل ڪندس ته جيئن اسان انهن گروپن جي لسٽ ڏسي سگهون ٿا جن جي صارف رڪنيت حاصل ڪئي آهي. هاڻي اهو سڀ ڪجهه چيڪ ڪرڻ سٺو ٿيندو. هن کي ڪرڻ لاء، اسان ٽيليگرام ۾ سڀني عملن کي انجام ڏينداسين ۽ ڊيٽابيس ۾ چيڪ ڪنداسين. جيئن ته اسان وٽ لکيل امتحان آهن، سڀ ڪجهه ٺيڪ هجڻ گهرجي. مضمون اڳ ۾ ئي ڪافي ڊگهو آهي، تنهنڪري اسان بعد ۾ AddGroupSubCommand لاءِ ٽيسٽ لکنداسين، ۽ ڪوڊ ۾ TODO شامل ڪنداسين ته جيئن وساري نه وڃي.

نتيجا

هن آرٽيڪل ۾، اسان سڄي ايپليڪيشن ذريعي ڪارڪردگي شامل ڪرڻ جي ڪم کي ڏٺو، ڊيٽابيس کان شروع ٿئي ٿو ۽ ڪلائنٽ سان ڪم ڪرڻ سان ختم ڪري ٿو جيڪو بوٽ استعمال ڪري ٿو. عام طور تي اهڙيون ڪم منصوبي کي سمجهڻ ۽ ان جي جوهر کي سمجهڻ ۾ مدد ڪن ٿيون. سمجھو ته اهو ڪيئن ڪم ڪري ٿو. انهن ڏينهن ۾ موضوع آسان نه آهن، تنهنڪري شرم نه ٿيو: پنهنجا سوال تبصرن ۾ لکو، ۽ مان انهن جا جواب ڏيڻ جي ڪوشش ڪندس. ڇا توھان پروجيڪٽ پسند ڪيو؟ Github تي هڪ اسٽار ڏيو : هن طريقي سان اهو واضح ٿيندو ته اهي منصوبي ۾ دلچسپي وٺندا آهن، ۽ مان خوش ٿيندس. جيئن ته چوندا آهن، هڪ ماسٽر هميشه خوش ٿيندو آهي جڏهن سندس ڪم کي ساراهيو ويندو آهي. ڪوڊ STEP_6 جي سڀني ٽن حصن تي مشتمل هوندو ۽ هن آرٽيڪل کان اڳ موجود هوندو. ان جي باري ۾ ڪيئن معلوم ڪرڻ لاء؟ اهو آسان آهي - ٽيليگرام چينل ۾ شامل ٿيو ، جتي آئون ٽيليگرام بوٽ بابت منهنجي مضمونن بابت سڀ معلومات شايع ڪريان ٿو. پڙهڻ لاءِ مهرباني! حصو 3 اڳ ۾ ئي هتي آهي .

سيريز ۾ سڀني مواد جي هڪ فهرست هن مضمون جي شروعات ۾ آهي.

تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION