JavaRush /Java Blog /Random-TK /Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçireliň...

Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçireliň. (2-nji bölüm) - "A-dan Z-a çenli Java taslamasy"

Toparda çap edildi

Programma üçin synaglar ýazýarys

Makalanyň başy: JRTB-3 ýazmak . Indi synag hakda pikirlenmeli. Addedhli goşulan kodlar, işleýşimiziň garaşyşymyz ýaly işleýändigine göz ýetirmek üçin synaglar bilen örtülmelidir. Ilki bilen SendBotMessageService hyzmaty üçin birlik synaglaryny ýazarys.
Bölüm synagy, programmanyň käbir ownuk böleginiň logikasyny barlaýan synag: köplenç bu usullar. Bu usuly bolan ähli baglanyşyklar, masgaralary ulanyp ýasama baglanyşyklar bilen çalşyrylýar.
Indi hemme zady görersiň. Şol bir paketde, diňe ./src/test/java bukjasynda , synap görjek synpymyz bilen birmeňzeş at döredýäris we ahyrynda Test goşarys . Sendagny, SendBotMessageService üçin SendBotMessageServiceTest bolar , bu synp üçin ähli synaglary öz içine alar. Synagdaky pikir şeýleräk: ýasama (ýasama) JavaRushTelegarmBot-a süýşýäris, soň ýerine ýetiriş usulynyň şeýle argument bilen çagyrylandygyny ýa-da ýokdugyny soraýarys. Ine, näme boldy:
package com.github.javarushcommunity.jrtb.service;

import com.github.javarushcommunity.jrtb.bot.JavarushTelegramBot;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

@DisplayName("Unit-level testing for SendBotMessageService")
public class SendBotMessageServiceTest {

   private SendBotMessageService sendBotMessageService;
   private JavarushTelegramBot javarushBot;

   @BeforeEach
   public void init() {
       javarushBot = Mockito.mock(JavarushTelegramBot.class);
       sendBotMessageService = new SendBotMessageServiceImpl(javarushBot);
   }

   @Test
   public void shouldProperlySendMessage() throws TelegramApiException {
       //given
       String chatId = "test_chat_id";
       String message = "test_message";

       SendMessage sendMessage = new SendMessage();
       sendMessage.setText(message);
       sendMessage.setChatId(chatId);
       sendMessage.enableHtml(true);

       //when
       sendBotMessageService.sendMessage(chatId, message);

       //then
       Mockito.verify(javarushBot).execute(sendMessage);
   }
}
Mockito-dan peýdalanyp, hyzmatymyzyň konstruktoryna gowşurylan JavaRushBot obýektini döretdim. Soň bolsa, bir synag ýazdym (Test düşündirişli her usul aýratyn synag). Bu usulyň gurluşy elmydama birmeňzeş - hiç hili argument talap etmeýär we boş gaýdyp gelýär. Synag ady, synag edýän zatlarymyzy aýtmalydyr. Biziň ýagdaýymyzda, bu: habary dogry ibermeli - habary dogry ibermeli. Synagymyz üç bölege bölünýär:
  • blok // berilýär - synag üçin zerur zatlary taýýarlaýan ýerimizde;
  • blokirleme // haçan - synag etmegi meýilleşdirýän usulymyzy nirede başlaýarys;
  • // soň blokirläň - usulyň dogry işleýändigini ýa-da ýokdugyny barlaýarys.
Hyzmatymyzdaky logika şu wagta çenli ýönekeý bolansoň, bu synp üçin bir synag ýeterlik bolar. Indi CommandContainer üçin synag ýazalyň:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.junit.jupiter.api.Assertions;
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.Arrays;

@DisplayName("Unit-level testing for CommandContainer")
class CommandContainerTest {

   private CommandContainer commandContainer;

   @BeforeEach
   public void init() {
       SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
       commandContainer = new CommandContainer(sendBotMessageService);
   }

   @Test
   public void shouldGetAllTheExistingCommands() {
       //when-then
       Arrays.stream(CommandName.values())
               .forEach(commandName -> {
                   Command command = commandContainer.retrieveCommand(commandName.getCommandName());
                   Assertions.assertNotEquals(UnknownCommand.class, command.getClass());
               });
   }

   @Test
   public void shouldReturnUnknownCommand() {
       //given
       String unknownCommand = "/fgjhdfgdfg";

       //when
       Command command = commandContainer.retrieveCommand(unknownCommand);

       //then
       Assertions.assertEquals(UnknownCommand.class, command.getClass());
   }
}
Bu gaty bir synag däl. Konteýneriň logikasyna daýanýar. Botyň goldaýan ähli buýruklary CommandName sanawynda we konteýnerde bolmaly. Şeýdip, CommandName üýtgeýjileriniň hemmesini aldym, Stream API-e gitdim we hersi üçin konteýnerden buýruk gözledim. Şeýle buýruk bolmadyk bolsa, UnknownCommand yzyna gaýtarylardy. Bu setirde barlaýan zatlarymyz:
Assertions.assertNotEquals(UnknownCommand.class, command.getClass());
“UnknownCommand” -yň deslapky boljakdygyny barlamak üçin aýratyn synag gerek - “ ReturnUnknownCommand” . Bu synaglary täzeden ýazmagyňyzy we derňemegiňizi maslahat berýärin. Toparlar üçin häzirlikçe ýarym resmi synaglar bolar, ýöne ýazylmaly. Logika SendBotMessageService synagy bilen deň bolar, şonuň üçin umumy synag logikasyny AbstractCommandTest synpyna geçirerin we her bir synag synagy miras galar we zerur meýdanlary kesgitlär. Synaglaryň hemmesi birmeňzeş bolansoň, her gezek şol bir zady ýazmak aňsat däl, üstesine-de bu gowy koduň alamaty däl. Umumylaşdyrylan abstrakt synp şeýle boldy:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.bot.JavarushTelegramBot;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.SendBotMessageServiceImpl;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.internal.verification.VerificationModeFactory;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

/**
* Abstract class for testing {@link Command}s.
*/
abstract class AbstractCommandTest {

   protected JavarushTelegramBot javarushBot = Mockito.mock(JavarushTelegramBot.class);
   protected SendBotMessageService sendBotMessageService = new SendBotMessageServiceImpl(javarushBot);

   abstract String getCommandName();

   abstract String getCommandMessage();

   abstract Command getCommand();

   @Test
   public void shouldProperlyExecuteCommand() throws TelegramApiException {
       //given
       Long chatId = 1234567824356L;

       Update update = new Update();
       Message message = Mockito.mock(Message.class);
       Mockito.when(message.getChatId()).thenReturn(chatId);
       Mockito.when(message.getText()).thenReturn(getCommandName());
       update.setMessage(message);

       SendMessage sendMessage = new SendMessage();
       sendMessage.setChatId(chatId.toString());
       sendMessage.setText(getCommandMessage());
       sendMessage.enableHtml(true);

       //when
       getCommand().execute(update);

       //then
       Mockito.verify(javarushBot).execute(sendMessage);
   }
}
Görşüňiz ýaly, her buýrugyň şu ýerde ýazylan synagy işletmeli we dogry ýerine ýetirmelidigini kesgitlänimizden soň, üç sany abstrakt usul bar. Esasy logika abstrakt synpda bolanda şeýle amatly çemeleşme, ýöne jikme-jiklikler nesillerde kesgitlenýär. Aslynda, bu ýerde anyk synaglaryň ýerine ýetirilişi bar:

KömekCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.HELP;
import static com.github.javarushcommunity.jrtb.command.HelpCommand.HELP_MESSAGE;

@DisplayName("Unit-level testing for HelpCommand")
public class HelpCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return HELP.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return HELP_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new HelpCommand(sendBotMessageService);
   }
}

NoCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.NO;
import static com.github.javarushcommunity.jrtb.command.NoCommand.NO_MESSAGE;

@DisplayName("Unit-level testing for NoCommand")
public class NoCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return NO.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return NO_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new NoCommand(sendBotMessageService);
   }
}

StartCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.START;
import static com.github.javarushcommunity.jrtb.command.StartCommand.START_MESSAGE;

@DisplayName("Unit-level testing for StartCommand")
class StartCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return START.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return START_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new StartCommand(sendBotMessageService);
   }
}

StopCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.CommandName.STOP;
import static com.github.javarushcommunity.jrtb.command.StopCommand.STOP_MESSAGE;

@DisplayName("Unit-level testing for StopCommand")
public class StopCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return STOP.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return STOP_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new StopCommand(sendBotMessageService);
   }
}

NäbelliCommandTest:

package com.github.javarushcommunity.jrtb.command;

import org.junit.jupiter.api.DisplayName;

import static com.github.javarushcommunity.jrtb.command.UnknownCommand.UNKNOWN_MESSAGE;

@DisplayName("Unit-level testing for UnknownCommand")
public class UnknownCommandTest extends AbstractCommandTest {

   @Override
   String getCommandName() {
       return "/fdgdfgdfgdbd";
   }

   @Override
   String getCommandMessage() {
       return UNKNOWN_MESSAGE;
   }

   @Override
   Command getCommand() {
       return new UnknownCommand(sendBotMessageService);
   }
}
Oýunyň şemiň gymmatdygy düşnüklidir we AbstractCommandTest-iň kömegi bilen ýazmak aňsat we düşünmek aňsat bolan ýönekeý we düşnükli synaglar bilen gutardyk. Mundan başga-da, gereksiz kodlary köpeltmekden halas bolduk (DRY-a salam -> Özüňizi gaýtalamaň). Mundan başga-da, indi programmanyň ýerine ýetirilişine baha berip biljek hakyky synaglarymyz bar. Botyň özi üçin synag ýazsaňam gowy bolardy, ýöne hemme zat aňsat we umuman netije bermez, belki, oýun olaryň aýdyşy ýaly şemiň gymmaty bolmaz. Şonuň üçin bu etapda biz öz işimizi tamamlarys. Iň soňky we iň halanýan zat - bir borçnama döredýäris, habar ýazýar: JRTB-3: Telegram Bot buýruklaryny dolandyrmak üçin buýruk nusgasy goşuldy we adat bolşy ýaly - Github çekmek haýyşyny döretmegi eýýäm bilýär we teklip edýär: "A-dan Z-a çenli Java taslamasy": Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçirmek.  2-nji bölümGurluşyk geçdi we siz eýýäm edip bilersiňiz birleşdir ... Nook! Taslama wersiýasyny täzeläp, RELEASE_NOTES-de ýazmagy ýatdan çykardym. Täze wersiýa bilen ýazgy goşýarys - 0.2.0-SNAPSHOT: "A-dan Z-a çenli Java taslamasy": Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçirmek.  2-nji bölümBu wersiýany pom.xml-de täzeleýäris we täze borçnama döredýäris: "A-dan Z-a çenli Java taslamasy": Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçirmek.  2-nji bölümTäze borçnama: JRTB-3: täzelenen RELEASE_NOTES.md"A-dan Z-a çenli Java taslamasy": Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçirmek.  2-nji bölüm Indi gurluşyň tamamlanmagyna basyň we garaşyň. Gurluşyk geçdi, birleşdirip bilersiňiz: "A-dan Z-a çenli Java taslamasy": Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçirmek.  2-5-nji bölümMen şahany pozamok, şonuň üçin hemişe üýtgän zady görüp we deňeşdirip bilersiňiz. Iş toparymyz täzelendi:"A-dan Z-a çenli Java taslamasy": Bot bilen işlemek üçin buýruk nusgasyny durmuşa geçirmek.  2-nji bölüm

Netijeler

Bu gün uly bir iş etdik: iş üçin buýruk şablonyny hödürledik. Hemme zat düzüldi, indi täze topar goşmak ýönekeý we gönümel iş bolar. Synag barada hem şu gün gürleşdik. Hatda toparlar üçin dürli synaglarda kody gaýtalamazlyk bilen azajyk oýnadyk. Hemişe bolşy ýaly, GitHub-da hasaba durmagy we bu seriýany we şol ýerde işleýän beýleki taslamalarymy yzarlamak üçin hasabymy yzarlamagy maslahat berýärin . Şeýle hem , täze makalalaryň çykmagyny köpeltjek telegram kanalyny döretdim . Bir gyzykly zat, kod adatça makalanyň özünden bir hepde öň çykýar we kanala her gezek täze bir iş gutarandan soň ýazaryn, bu makalany okamazdan ozal kody anyklamaga mümkinçilik berer. Soonakyn wagtda boty yzygiderli esasda çap ederin we telegram kanalyna ýazylanlar bu barada ilkinji bolup bilerler;) Okanyňyz üçin sag boluň, dowamy.

Tapgyryň ähli materiallarynyň sanawy bu makalanyň başynda.

Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION