JavaRush /Blog Jawa /Random-JV /Kita nambah kabeh sing ana gandhengane karo database. (Ba...

Kita nambah kabeh sing ana gandhengane karo database. (Bagian 2) - "Proyek Jawa saka A nganti Z"

Diterbitake ing grup
Halo kabeh. Ayo kula ngelingake sampeyan: ing bagean pisanan ditambahake Flyway. Ayo diterusake.

Nambahake database menyang docker-compose.yml

Tahap sabanjure nyiyapake karya karo database ing docker-compose.yml utama. Ayo nambahake database menyang file docker-compose:
version: '3.1'

services:
 jrtb-bot:
   depends_on:
     - jrtb-db
   build:
     context: .
   environment:
     BOT_NAME: ${BOT_NAME}
     BOT_TOKEN: ${BOT_TOKEN}
     BOT_DB_USERNAME: ${BOT_DB_USERNAME}
     BOT_DB_PASSWORD: ${BOT_DB_PASSWORD}
   restart: always
 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'
Aku uga nambahake baris iki menyang aplikasi kita:
depends_on:
 - jrtb-db
Iki tegese kita ngenteni database diwiwiti sadurunge miwiti aplikasi. Sabanjure, sampeyan bisa ndeleng tambahan rong variabel liyane sing kudu digarap database:
${BOT_DB_USERNAME}
${BOT_DB_PASSWORD}
Kita bakal nggawe docker-compose kanthi cara sing padha karo bot telegram - liwat variabel lingkungan. Aku nindakake iki supaya kita mung duwe siji panggonan kanggo nyetel nilai jeneng pangguna database lan sandhi. Kita ngirim menyang gambar docker aplikasi kita lan menyang wadhah docker database kita. Sabanjure, kita kudu nganyari Dockerfile kanggo mulang SpringBoot kanggo nampa variabel kanggo database.
FROM adoptopenjdk/openjdk11:ubi
ARG JAR_FILE=target/*.jar
ENV BOT_NAME=test.javarush_community_bot
ENV BOT_TOKEN=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
ENV BOT_DB_USERNAME=jrtb_db_user
ENV BOT_DB_PASSWORD=jrtb_db_password
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Dspring.datasource.password=${BOT_DB_PASSWORD}", "-Dbot.username=${BOT_NAME}", "-Dbot.token=${BOT_TOKEN}", "-Dspring.datasource.username=${BOT_DB_USERNAME}", "-jar", "app.jar"]
Saiki kita nambah variabel database menyang Dockerfile:
ENV BOT_DB_USERNAME=jrtb_db_user
ENV BOT_DB_PASSWORD=jrtb_db_password
Nilai variabel bakal beda. Sing bakal kita lebokake menyang Dockerfile, nanging mbutuhake nilai standar, mula aku ngetik sawetara. Kita nggedhekake baris pungkasan kanthi rong unsur, kanthi bantuan bakal menehi jeneng pangguna lan sandhi DB menyang peluncuran aplikasi:
"-Dspring.datasource.password=${BOT_DB_PASSWORD}", "-Dbot.username=${BOT_NAME}"
Baris pungkasan ing Dockerfile (sing diwiwiti karo ENTRYPOINT) kudu tanpa bungkus. Yen sampeyan nggawe transfer, kode iki ora bisa digunakake. Langkah pungkasan kanggo nganyari file start.sh kanggo pass variabel menyang database.
#!/bin/bash

# Pull new changes
git pull

# Prepare Jar
mvn clean
mvn package

# Ensure, that docker-compose stopped
docker-compose stop

# Add environment variables
export BOT_NAME=$1
export BOT_TOKEN=$2
export BOT_DB_USERNAME='prod_jrtb_db_user'
export BOT_DB_PASSWORD='Pap9L9VVUkNYj99GCUCC3mJkb'

# Start new deployment
docker-compose up --build -d
Kita wis ngerti carane nambah variabel lingkungan sadurunge mbukak docker-compose. Kanggo nindakake iki, sampeyan mung kudu nglakokaké export var_name=var_value.. Mulane, kita nambah mung rong baris:
export BOT_DB_USERNAME='prod_jrtb_db_user'
export BOT_DB_PASSWORD='Pap9L9VVUkNYj99GCUCC3mJkb'
Iki ngendi kita nyetel jeneng pangguna lan sandhi database. Mesthi wae, bakal bisa ngliwati variabel kasebut nalika mbukak skrip bash, kaya sing ditindakake kanggo jeneng lan token bot. Nanging misale jek aku iki ora perlu. Kanggo bener ngakses database, sampeyan kudu ngerti IP saka server kang database bakal disebarake, lan ing dhaftar alamat IP diijini kanggo request. Dene kula, punika sampun cekap. Yayasan wis dilebokake: saiki sampeyan bisa nindakake perkara sing luwih bisa dingerteni kanggo pangembang - nulis kode. Sadurunge, kita nindakake apa sing ditindakake para insinyur DevOps - nyetel lingkungan.

Nambahake lapisan Repositori

Biasane aplikasi duwe telung lapisan:
  1. Pengontrol minangka titik entri menyang aplikasi.
  2. Layanan ing ngendi logika bisnis bisa digunakake. Kita wis sebagian duwe iki: SendMessageService minangka perwakilan eksplisit saka logika bisnis.
  3. Repositori minangka papan kanggo nggarap database. Ing kasus kita, iki minangka bot telegram.
Saiki kita bakal nambah lapisan katelu - repositori. Ing kene kita bakal nggunakake proyek saka ekosistem Spring - Spring Data. Sampeyan bisa maca babagan apa sing ana ing artikel iki babagan Habré . Kita kudu ngerti lan ngerti sawetara poin:
  1. Kita ora kudu nggarap JDBC: kita bakal langsung nggarap abstraksi sing luwih dhuwur. Yaiku, nyimpen POJO sing cocog karo tabel ing basis data. Kita bakal nelpon entitas kelas kasebut , amarga kasebut kanthi resmi ing Java Persistence API (iki minangka antarmuka umum kanggo nggarap database liwat ORM, yaiku, abstraksi babagan nggarap JDBC). Kita bakal duwe kelas entitas sing bakal disimpen ing database, lan bakal ditulis persis ing tabel sing dibutuhake. Kita bakal nampa obyek sing padha nalika nggoleki ing database.
  2. Spring Data nawakake kanggo nggunakake pesawat saka antarmuka: JpaRepository , CrudRepository , etc ... Ana antarmuka liyane: dhaftar lengkap bisa ditemokaké kene . Kaendahane yaiku sampeyan bisa nggunakake metode kasebut tanpa ngetrapake (!). Kajaba iku, ana cithakan tartamtu sing bisa digunakake kanggo nulis cara anyar ing antarmuka, lan bakal ditindakake kanthi otomatis.
  3. Spring nyederhanakake pangembangan kita sabisa. Kanggo nindakake iki, kita kudu nggawe antarmuka dhewe lan warisan saka sing kasebut ing ndhuwur. Lan supaya Spring ngerti yen kudu nggunakake antarmuka iki, tambahake anotasi Repositori.
  4. Yen kita kudu nulis cara kanggo nggarap database sing ora ana, mula iki uga ora dadi masalah - kita bakal nulis. Aku bakal nuduhake sampeyan apa lan carane nindakake ing kana.
Ing artikel iki, kita bakal bisa nambah kabeh dalan TelegramUser lan nuduhake bagean iki minangka conto. Kita bakal nggedhekake liyane ing tugas liyane. Yaiku, nalika kita nglakokake perintah / start, kita bakal nulis active = true menyang database pangguna. Iki tegese pangguna nggunakake bot. Yen pangguna wis ana ing database, kita bakal nganyari lapangan aktif = bener. Nalika nglakokaké printah / mandeg, kita ora bakal mbusak pangguna, nanging mung bakal nganyari lapangan aktif kanggo palsu, supaya yen pangguna pengin nggunakake bot maneh, kang bisa miwiti lan Pick munggah ngendi kang kiwa. Lan supaya nalika nyoba kita bisa ndeleng manawa ana kedadeyan, kita bakal nggawe perintah / stat: bakal nampilake jumlah pangguna sing aktif. Kita nggawe paket repositori ing jejere bot, printah, paket layanan. Ing paket iki kita nggawe entitas siji liyane . Ing paket entitas, kita nggawe kelas TelegramUser:
package com.github.javarushcommunity.jrtb.repository.entity;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

/**
* Telegram User entity.
*/
@Data
@Entity
@Table(name = "tg_user")
public class TelegramUser {

   @Id
   @Column(name = "chat_id")
   private String chatId;

   @Column(name = "active")
   private boolean active;
}
Ing kene sampeyan bisa ndeleng manawa ana kabeh anotasi saka paket javax.persistence. Iki minangka anotasi umum sing digunakake kanggo kabeh implementasi ORM. Kanthi gawan, Spring Data Jpa nggunakake Hibernate, sanajan implementasi liyane bisa digunakake. Mangkene dhaptar anotasi sing digunakake:
  • Entitas - nuduhake yen iki minangka entitas kanggo nggarap database;
  • Tabel - kene kita nemtokake jeneng meja;
  • Id - anotasi nyatakake lapangan sing bakal dadi Kunci Utama ing tabel;
  • Column - nemtokake jeneng lapangan saka tabel.
Sabanjure, kita nggawe antarmuka kanggo nggarap database. Biasane, jeneng antarmuka kasebut ditulis nggunakake cithakan - EntiryNameRepository. Kita bakal duwe TelegramuserRepository:
package com.github.javarushcommunity.jrtb.repository;

import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
* {@link Repository} for handling with {@link TelegramUser} entity.
*/
@Repository
public interface TelegramUserRepository extends JpaRepository<TelegramUser, String> {
   List<TelegramUser> findAllByActiveTrue();
}
Ing kene sampeyan bisa ndeleng carane aku nambah cara findAllByActiveTrue () , sing aku ora ngleksanakake ing ngendi wae. Nanging iki ora bakal ngalangi dheweke kerja. Spring Data bakal ngerti yen perlu kanggo njupuk kabeh cathetan saka tg_user tabel sing kolom aktif = bener . Kita nambah layanan kanggo nggarap entitas TelegramUser (kita nggunakake inversi dependensi saka SOLID ing konteks layanan entitas liya ora bisa langsung komunikasi karo gudang entitas liya - mung liwat layanan entitas kasebut). Kita nggawe layanan TelegramUserService ing paket, sing saiki bakal duwe sawetara cara: nyimpen pangguna, entuk pangguna kanthi ID lan nampilake dhaptar pangguna aktif. Pisanan kita nggawe antarmuka TelegramUserService:
package com.github.javarushcommunity.jrtb.service;

import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
* {@link Service} for handling {@link TelegramUser} entity.
*/
public interface TelegramUserService {

   /**
    * Save provided {@link TelegramUser} entity.
    *
    * @param  telegramUser provided telegram user.
    */
   void save(TelegramUser telegramUser);

   /**
    * Retrieve all active {@link TelegramUser}.
    *
    * @return the collection of the active {@link TelegramUser} objects.
    */
   List<TelegramUser> retrieveAllActiveUsers();

   /**
    * Find {@link TelegramUser} by chatId.
    *
    * @param chatId provided Chat ID
    * @return {@link TelegramUser} with provided chat ID or null otherwise.
    */
   Optional<TelegramUser> findByChatId(String chatId);
}
Lan, nyatane, implementasine TelegramUserServiceImpl:
package com.github.javarushcommunity.jrtb.service;

import com.github.javarushcommunity.jrtb.repository.TelegramUserRepository;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
* Implementation of {@link TelegramUserService}.
*/
@Service
public class TelegramUserServiceImpl implements TelegramUserService {

   private final TelegramUserRepository telegramUserRepository;

   @Autowired
   public TelegramUserServiceImpl(TelegramUserRepository telegramUserRepository) {
       this.telegramUserRepository = telegramUserRepository;
   }

   @Override
   public void save(TelegramUser telegramUser) {
       telegramUserRepository.save(telegramUser);
   }

   @Override
   public List<TelegramUser> retrieveAllActiveUsers() {
       return telegramUserRepository.findAllByActiveTrue();
   }

   @Override
   public Optional<TelegramUser> findByChatId(String chatId) {
       return telegramUserRepository.findById(chatId);
   }
}
Ing kene kudu dicathet yen kita nggunakake injeksi dependensi (ngenalake conto kelas) obyek TelegramuserRepository nggunakake anotasi Autowired , lan ing konstruktor. Sampeyan bisa nindakake iki kanggo variabel, nanging iki pendekatan sing disaranake tim Spring Framework kanggo kita.

Nambahake statistik kanggo bot

Sabanjure sampeyan kudu nganyari printah / miwiti lan / mungkasi. Nalika printah / miwiti digunakake, sampeyan kudu nyimpen pangguna anyar ing database lan nyetel menyang aktif = bener. Lan nalika ana / mandeg, nganyari data pangguna: nyetel aktif = palsu. Ayo ndandani kelas StartCommand :
package com.github.javarushcommunity.jrtb.command;

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;

/**
* Start {@link Command}.
*/
public class StartCommand implements Command {

   private final SendBotMessageService sendBotMessageService;
   private final TelegramUserService telegramUserService;

   public final static String START_MESSAGE = "Привет. Я Javarush Telegram Bot. Я помогу тебе быть в курсе последних " +
           "статей тех авторов, котрые тебе интересны. Я еще маленький и только учусь.";

   public StartCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
       this.sendBotMessageService = sendBotMessageService;
       this.telegramUserService = telegramUserService;
   }

   @Override
   public void execute(Update update) {
       String chatId = update.getMessage().getChatId().toString();

       telegramUserService.findByChatId(chatId).ifPresentOrElse(
               user -> {
                   user.setActive(true);
                   telegramUserService.save(user);
               },
               () -> {
                   TelegramUser telegramUser = new TelegramUser();
                   telegramUser.setActive(true);
                   telegramUser.setChatId(chatId);
                   telegramUserService.save(telegramUser);
               });

       sendBotMessageService.sendMessage(chatId, START_MESSAGE);
   }
}
Ing kene kita uga ngirim obyek TelegramuserService menyang konstruktor, sing bakal disimpen pangguna anyar. Luwih, nggunakake ditresnani saka Opsional ing Jawa, logika ing ngisor iki dianggo: yen kita duwe pangguna ing database, kita mung nggawe wong aktif, yen ora, kita nggawe anyar aktif. StopCommand:
package com.github.javarushcommunity.jrtb.command;

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 java.util.Optional;

/**
* Stop {@link Command}.
*/
public class StopCommand implements Command {

   private final SendBotMessageService sendBotMessageService;
   private final TelegramUserService telegramUserService;

   public static final String STOP_MESSAGE = "Деактивировал все ваши подписки \uD83D\uDE1F.";

   public StopCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
       this.sendBotMessageService = sendBotMessageService;
       this.telegramUserService = telegramUserService;
   }

   @Override
   public void execute(Update update) {
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), STOP_MESSAGE);
       telegramUserService.findByChatId(update.getMessage().getChatId().toString())
               .ifPresent(it -> {
                   it.setActive(false);
                   telegramUserService.save(it);
               });
   }
}
Kita ngliwati TelegramServiceTest menyang StopCommand kanthi cara sing padha. Logika tambahan yaiku: yen kita duwe pangguna sing duwe ID chatting, kita mateni, yaiku, kita nyetel aktif = palsu. Kepiye carane sampeyan bisa ndeleng iki kanthi mripatmu dhewe? Ayo nggawe printah anyar / stat, sing bakal nampilake statistik bot. Ing tahap iki, iki bakal dadi statistik prasaja sing kasedhiya kanggo kabeh pangguna. Ing mangsa ngarep, kita bakal mbatesi lan nggawe akses mung kanggo pangurus. Bakal ana siji entri ing statistik: jumlah pangguna bot sing aktif. Kanggo nindakake iki, tambahake nilai STAT("/stat") menyang CommandName. Sabanjure, gawe kelas StatCommand :
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.telegram.telegrambots.meta.api.objects.Update;

/**
* Statistics {@link Command}.
*/
public class StatCommand implements Command {

   private final TelegramUserService telegramUserService;
   private final SendBotMessageService sendBotMessageService;

   public final static String STAT_MESSAGE = "Javarush Telegram Bot использует %s человек.";

   @Autowired
   public StatCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
       this.sendBotMessageService = sendBotMessageService;
       this.telegramUserService = telegramUserService;
   }

   @Override
   public void execute(Update update) {
       int activeUserCount = telegramUserService.retrieveAllActiveUsers().size();
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), String.format(STAT_MESSAGE, activeUserCount));
   }
}
Kabeh gampang ing kene: kita entuk dhaptar kabeh pangguna aktif nggunakake metode retrieveAllActiveUsers lan entuk ukuran koleksi. Kita uga saiki kudu nganyari kelas munggah: CommandContainer lan JavarushTelegramBot supaya padha sinau kanggo pass layanan anyar kita perlu. CommandContainer:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import com.google.common.collect.ImmutableMap;

import static com.github.javarushcommunity.jrtb.command.CommandName.*;

/**
* Container of the {@link Command}s, which are using for handling telegram commands.
*/
public class CommandContainer {

   private final ImmutableMap<String, Command> commandMap;
   private final Command unknownCommand;

   public CommandContainer(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {

       commandMap = ImmutableMap.<String, Command>builder()
               .put(START.getCommandName(), new StartCommand(sendBotMessageService, telegramUserService))
               .put(STOP.getCommandName(), new StopCommand(sendBotMessageService, telegramUserService))
               .put(HELP.getCommandName(), new HelpCommand(sendBotMessageService))
               .put(NO.getCommandName(), new NoCommand(sendBotMessageService))
               .put(STAT.getCommandName(), new StatCommand(sendBotMessageService, telegramUserService))
               .build();

       unknownCommand = new UnknownCommand(sendBotMessageService);
   }

   public Command retrieveCommand(String commandIdentifier) {
       return commandMap.getOrDefault(commandIdentifier, unknownCommand);
   }

}
Ing kene kita nambahake perintah anyar menyang peta lan ngliwati konstruktor TelegramUserService. Nanging ing bot kasebut, mung konstruktor sing bakal diganti:
@Autowired
public JavarushTelegramBot(TelegramUserService telegramUserService) {
   this.commandContainer = new CommandContainer(new SendBotMessageServiceImpl(this), telegramUserService);
}
Saiki kita ngliwati TelegramUserService minangka argumen, nambah anotasi Autowired. Iki tegese kita bakal nampa saka Konteks Aplikasi. Kita uga bakal nganyari kelas HelpCommand supaya printah statistik anyar katon ing gambaran.

Tes manual

Ayo miwiti database saka docker-compose-test.yml lan cara utama ing kelas JavarushTelegramBotApplication. Sabanjure kita nulis sakumpulan printah:
  • / stat - kita ngarepake yen database kosong, bakal ana nol wong sing nggunakake bot iki;
  • / miwiti - miwiti bot;
  • / stat - saiki kita ngarepake yen bot bakal digunakake dening 1 wong;
  • / mandeg - mungkasi bot;
  • / stat - kita nyana yen maneh bakal ana 0 wong nggunakake.
"Proyek Jawa saka A nganti Z": Nambahake kabeh sing ana gandhengane karo database.  Bagean 2 - 2Yen asile padha kanggo sampeyan, kita bisa ujar manawa fungsi kasebut bisa digunakake kanthi bener lan bot bisa digunakake kanthi bener. Yen ana sing salah, ora masalah: kita miwiti maneh cara utama ing mode debug lan kanthi jelas ngliwati kabeh dalan kanggo nemokake kesalahane.

Kita nulis lan nganyari tes

Awit kita ngganti konstruktor, kita uga kudu nganyari kelas test. Ing kelas AbstractCommandTest , kita kudu nambah siji lapangan - kelas TelegramUserService , sing dibutuhake kanggo telung printah:
protected TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);
Sabanjure, ayo nganyari metode init() ing CommandContainer :
@BeforeEach
public void init() {
   SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
   TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);
   commandContainer = new CommandContainer(sendBotMessageService, telegramUserService);
}
Ing StartCommand sampeyan kudu nganyari metode getCommand() :
@Override
Command getCommand() {
   return new StartCommand(sendBotMessageService, telegramUserService);
}
Uga ing StopCommand:
@Override
Command getCommand() {
   return new StopCommand(sendBotMessageService, telegramUserService);
}
Sabanjure, ayo goleki tes anyar. Ayo nggawe tes khas kanggo StatCommand :
package com.github.javarushcommunity.jrtb.command;

import static com.github.javarushcommunity.jrtb.command.CommandName.STAT;
import static com.github.javarushcommunity.jrtb.command.StatCommand.STAT_MESSAGE;

public class StatCommandTest extends AbstractCommandTest {
   @Override
   String getCommandName() {
       return STAT.getCommandName();
   }

   @Override
   String getCommandMessage() {
       return String.format(STAT_MESSAGE, 0);
   }

   @Override
   Command getCommand() {
       return new StatCommand(sendBotMessageService, telegramUserService);
   }
}
Iki prasaja. Saiki ayo ngomong babagan carane nyoba nggarap database. Kabeh sing ditindakake sadurunge yaiku tes unit. Tes integrasi nguji integrasi antarane sawetara bagean aplikasi. Contone, aplikasi lan database. Ing kene kabeh bakal luwih rumit, amarga kanggo nguji kita butuh database sing disebarake. Mulane, nalika kita mbukak tes kita sacara lokal, kita kudu duwe database mbukak saka docker-compose-test.yml. Kanggo mbukak test iki, sampeyan kudu mbukak kabeh aplikasi SpringBoot. Kelas test duwe anotasi SpringBootTest sing bakal miwiti aplikasi. Nanging pendekatan iki ora bisa digunakake kanggo kita, amarga nalika aplikasi diluncurake, bot telegram uga bakal diluncurake. Nanging ana kontradiksi ing kene. Tes bakal ditindakake sacara lokal ing mesin kita lan kanthi umum liwat Tindakan GitHub. Supaya tes bisa lulus kanthi diluncurake kabeh aplikasi, kita kudu mbukak kanthi data sing bener ing bot telegram: yaiku, kanthi jeneng lan token ... Mulane, kita duwe rong pilihan:
  1. Dadi nggawe jeneng lan token bot umum lan ngarep-arep kabeh bakal apik, ora ana sing bakal nggunakake lan ngganggu kita.
  2. Teka karo cara liyane.
Aku milih pilihan kapindho. Pengujian SpringBoot nduweni anotasi DataJpaTest , sing digawe supaya nalika nguji database, kita mung nggunakake kelas sing dibutuhake lan ninggalake wong liya. Nanging iki cocog karo kita, amarga bot telegram ora bakal diluncurake. Iki tegese ora perlu menehi jeneng lan token sing bener!))) Kita bakal entuk tes sing bakal mriksa manawa metode sing ditindakake Data Spring kanggo kita bisa digunakake kaya sing dikarepake. Penting kanggo dicathet ing kene yen kita nggunakake anotasi @ActiveProfiles("test") kanggo nemtokake panggunaan profil test. Lan iki persis sing kita butuhake supaya bisa ngetung properti sing bener kanggo database kita. Luwih becik nyiyapake database sadurunge nglakokake tes. Ana pendekatan kasebut kanggo prakara iki: tambahake anotasi Sql menyang tes lan pass koleksi jeneng skrip sing kudu ditindakake sadurunge miwiti tes:
@Sql(scripts = {"/sql/clearDbs.sql", "/sql/telegram_users.sql"})
Kanggo kita, bakal ana ing sadawane dalan ./src/test/resources/ + path sing ditemtokake ing anotasi. Mangkene rupane:
clearDbs.sql:
DELETE FROM tg_user;

telegram_users.sql:
INSERT INTO tg_user VALUES ("123456789", 1);
INSERT INTO tg_user VALUES ("123456788", 1);
INSERT INTO tg_user VALUES ("123456787", 1);
INSERT INTO tg_user VALUES ("123456786", 1);
INSERT INTO tg_user VALUES ("123456785", 1);
INSERT INTO tg_user VALUES ("123456784", 0);
INSERT INTO tg_user VALUES ("123456782", 0);
INSERT INTO tg_user VALUES ("123456781", 0);
Iki minangka asil tes TelegramUserRepositoryIT kita (kaya sing sampeyan deleng, jeneng tes integrasi bakal beda - kita nambah IT, dudu Tes):
package com.github.javarushcommunity.jrtb.repository;

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 TelegramUserRepository}.
*/
@ActiveProfiles("test")
@DataJpaTest
@AutoConfigureTestDatabase(replace = NONE)
public class TelegramUserRepositoryIT {

   @Autowired
   private TelegramUserRepository telegramUserRepository;

   @Sql(scripts = {"/sql/clearDbs.sql", "/sql/telegram_users.sql"})
   @Test
   public void shouldProperlyFindAllActiveUsers() {
       //when
       List<TelegramUser> users = telegramUserRepository.findAllByActiveTrue();

       //then
       Assertions.assertEquals(5, users.size());
   }

   @Sql(scripts = {"/sql/clearDbs.sql"})
   @Test
   public void shouldProperlySaveTelegramUser() {
       //given
       TelegramUser telegramUser = new TelegramUser();
       telegramUser.setChatId("1234567890");
       telegramUser.setActive(false);
       telegramUserRepository.save(telegramUser);

       //when
       Optional<TelegramUser> saved = telegramUserRepository.findById(telegramUser.getChatId());

       //then
       Assertions.assertTrue(saved.isPresent());
       Assertions.assertEquals(telegramUser, saved.get());
   }
}
Kita nulis tes kasebut, nanging ana pitakonan: apa sing bakal kelakon karo peluncuran proses CI kita ing GitHub? Ora bakal duwe database. Kanggo saiki ana tenan mung bakal mbangun abang. Kanggo nindakake iki, kita duwe tumindak GitHub, ing ngendi kita bisa ngatur peluncuran bangunan kita. Sadurunge nglakokake tes, sampeyan kudu nambah peluncuran database kanthi setelan sing dibutuhake. Ternyata, ora ana akeh conto ing Internet, mula aku menehi saran supaya sampeyan nyimpen iki ing endi wae. Ayo nganyari file .github/workflows/maven.yml:
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Java CI with Maven

on:
 push:
   branches: [ main ]
 pull_request:
   branches: [ main ]

jobs:
 build:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@v2
   - name: Set up MySQL
     uses: mirromutth/mysql-action@v1.1
     with:
       mysql version: '5.7'
       mysql database: 'dev_jrtb_db'
       mysql root password: 'root'
       mysql user: 'dev_jrtb_db_user'
       mysql password: 'dev_jrtb_db_password'
   - name: Set up JDK 1.11
     uses: actions/setup-java@v1
     with:
       java-version: 1.11
   - name: Build with Maven
     run: mvn -B package --file pom.xml
Saiki ana blok Set up MySQL anyar . Ing kono kita nambah MySQL menyang proses CI kita, kanthi bebarengan nemtokake variabel sing kita butuhake. Saiki kita wis nambah kabeh sing dikarepake. Tahap pungkasan yaiku nyurung owah-owahan lan ndeleng manawa bangunan kasebut bakal dadi ijo.

Nganyari dokumentasi

Ayo nganyari versi proyek saka 0.3.0-SNAPSHOT dadi 0.4.0-SNAPSHOT ing pom.xml lan uga ditambahake menyang RELEASE_NOTES:
## 0.4.0-SNAPSHOT

*   JRTB-1: added repository layer.
Sawise kabeh iki, kita nggawe commit, push lan pull request. Lan sing paling penting, bangunan kita ijo!"Proyek Jawa saka A nganti Z": Nambahake kabeh sing ana gandhengane karo database.  Bagean 2 - 3

Pranala migunani:

Kabeh owah-owahan bisa katon ing kene ing request narik digawe . Matur nuwun kanggo kabeh sing wis maca.

Dhaptar kabeh materi ing seri kasebut ana ing wiwitan artikel iki.

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