JavaRush /Java blogi /Random-UZ /MySql-ni almashtirish uchun MariaDB-dan foydalangan holda...

MySql-ni almashtirish uchun MariaDB-dan foydalangan holda ma'lumotlar bazasini integratsiya sinovi

Guruhda nashr etilgan
MySql o'rnini MariaDB yordamida ma'lumotlar bazasini integratsiya testi - 1Bugun men test haqida gapirmoqchiman, chunki kod qanchalik ko'p testlar bilan qoplangan bo'lsa, u shunchalik yaxshi va ishonchli hisoblanadi. Keling, birlik testi haqida emas, balki ma'lumotlar bazalarining integratsion testlari haqida gapiraylik. Birlik testlari va integratsiya testlari o'rtasidagi aniq farq nima? MySql - 2 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinoviModulli (birlik) dasturni individual modullar, usullar yoki sinflar darajasida sinovdan o'tkazadi, ya'ni testlar tez va oson bo'lib, funksionallikning eng bo'linadigan qismlariga ta'sir qiladi. Ular, shuningdek, "har bir usul uchun bitta test" deb ataladi. Integratsiya sekinroq va og'irroq bo'lib, ular bir nechta modul va qo'shimcha funktsiyalardan iborat bo'lishi mumkin. MySql - 3 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinoviNima uchun dao (Ma'lumotlarga kirish ob'ekti) qatlami integratsiyasi testlari? Chunki ma'lumotlar bazasiga so'rovlar bilan usullarni sinab ko'rish uchun biz RAMda asosiysini almashtirgan holda alohida ma'lumotlar bazasini yaratishimiz kerak. G'oya shundan iboratki, biz kerakli jadvallarni yaratamiz, ularni test ma'lumotlari bilan to'ldiramiz va omborlar sinfi usullarining to'g'riligini tekshiramiz (oxir-oqibat, biz ma'lum bir holatda yakuniy natija qanday bo'lishi kerakligini bilamiz). Shunday ekan, boshlaylik. Ma'lumotlar bazasini ulash bo'yicha mavzular uzoq vaqtdan beri yoritilgan va shuning uchun bugun men bu haqda to'xtalmoqchi emasman va biz dasturning faqat bizni qiziqtirgan qismlarini ko'rib chiqamiz. Odatiy bo'lib, biz ilovamiz Spring Boot-ga asoslanganligidan boshlaymiz, Spring JDBC dao qatlami uchun (aniqlik uchun), bizning asosiy ma'lumotlar bazasi MySQL bo'lib, biz uni MariaDB yordamida almashtiramiz (ular maksimal darajada mos keladi va va shunga ko'ra MySQL skriptlari hech qachon MariaDB dialekti bilan ziddiyat bo'lmaydi, chunki H2 bilan bo'ladi). Shuningdek, biz shartli ravishda dasturimiz ma'lumotlar bazasi sxemasiga o'zgartirishlarni boshqarish va qo'llash uchun Liquibase-dan foydalanadi va shunga mos ravishda barcha qo'llaniladigan skriptlar bizning ilovamizda saqlanadi deb taxmin qilamiz.

Loyiha tuzilishi

Faqat ta'sirlangan qismlar ko'rsatiladi: MySql - 5 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinoviHa, bugun biz robotlar yaratamiz)) MySql - 6 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinoviJadval uchun skript, biz bugun sinab ko'radigan usullar (create_table_robots.sql):
CREATE TABLE `robots`
(
   `id`   BIGINT(20) NOT NULL AUTO_INCREMENT,
   `name` CHAR(255) CHARACTER SET utf8 NOT NULL,
   `cpu`  CHAR(255) CHARACTER SET utf8 NOT NULL,
   `producer`  CHAR(255) CHARACTER SET utf8 NOT NULL,
   PRIMARY KEY (`id`)
) ENGINE = InnoDB
 DEFAULT CHARSET = utf8;
Ushbu jadvalni ifodalovchi ob'ekt:
@Builder
@Data
public class Robot {

   private Long id;

   private String name;

   private String cpu;

   private String producer;
}
Sinov qilingan ombor uchun interfeys:
public interface RobotDAO {

   Robot findById(Long id);

   Robot create(Robot robot);

   List<Robot> findAll();

   Robot update(Robot robot);

   void delete(Long id);
}
Aslida, bu erda ekzotiksiz standart CRUD operatsiyalari mavjud, shuning uchun biz barcha usullarni emas (yaxshi, bu hech kimni ajablantirmaydi) amalga oshirishni ko'rib chiqamiz, lekin ba'zilari - qisqartirish uchun:
@Repository
@AllArgsConstructor
public class RobotDAOImpl implements RobotDAO {

   private static final String FIND_BY_ID = "SELECT id, name, cpu, producer FROM robots WHERE id = ?";

   private static final String UPDATE_BY_ID = "UPDATE robots SET name = ?, cpu = ?, producer = ?  WHERE id = ?";

   @Autowired
   private final JdbcTemplate jdbcTemplate;

   @Override
   public Robot findById(Long id) {
       return jdbcTemplate.queryForObject(FIND_BY_ID, robotMapper(), id);
   }

   @Override
   public Robot update(Robot robot) {
       jdbcTemplate.update(UPDATE_BY_ID,
               robot.getName(),
               robot.getCpu(),
               robot.getProducer(),
               robot.getId());

       return robot;
   }

   private RowMapper<Robot> robotMapper() {
       return (rs, rowNum) ->
               Robot.builder()
                       .id(rs.getLong("id"))
                       .name(rs.getString("name"))
                       .cpu(rs.getString("cpu"))
                       .producer(rs.getString("producer"))
                       .build();
   }
Keling, biroz chetga chiqamiz va bog'liqliklarimiz bilan nima sodir bo'layotganini ko'rib chiqamiz (faqat ilovaning ko'rsatilgan qismi uchun ishlatiladiganlar taqdim etiladi):
<dependencies>
   <dependency>
       <groupId>org.mariadb.jdbc</groupId>
       <artifactId>mariadb-java-client</artifactId>
       <version>2.5.2</version>
       <scope>test</scope>
   </dependency>
   <dependency>
       <groupId>org.craftercms.mariaDB4j</groupId>
       <artifactId>mariaDB4j-springboot</artifactId>
       <version>2.4.2.3</version>
       <scope>test</scope>
   </dependency>
   <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <version>1.18.10</version>
       <scope>provided</scope>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <version>2.2.1.RELEASE</version>
       <scope>test</scope>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jdbc</artifactId>
       <version>2.2.1.RELEASE</version>
   </dependency>
</dependencies>
4 - MariaDb ma'lumotlar bazasiga bog'liqlik 10 - SpringBoot 16 bilan ulanishga bog'liqlik - Lombok (menimcha, bu qanday lib ekanligini hamma biladi) 22 - sinov uchun starter (bizga kerak bo'lgan JUnit o'rnatilgan) 28 - starter springJdbc bilan ishlash Keling, sinovlarimiz uchun zarur bo'lgan loviya bilan bahor konteynerini ko'rib chiqaylik (xususan, MariaDB yaratish loviya):
@Configuration
public class TestConfigDB {

   @Bean
   public MariaDB4jSpringService mariaDB4jSpringService() {
       return new MariaDB4jSpringService();
   }

   @Bean
   public DataSource dataSource(MariaDB4jSpringService mariaDB4jSpringService) {
       try {
           mariaDB4jSpringService.getDB().createDB("testDB");
       } catch (ManagedProcessException e) {
         e.printStackTrace();
       }

       DBConfigurationBuilder config = mariaDB4jSpringService.getConfiguration();

       return DataSourceBuilder
               .create()
               .username("root")
               .password("root")
               .url(config.getURL("testDB"))
               .driverClassName("org.mariadb.jdbc.Driver")
               .build();
   }

   @Bean
   public JdbcTemplate jdbcTemplate(DataSource dataSource) {
       return new JdbcTemplate(dataSource);
   }
}
5 - MariaDB ni ko'tarish uchun asosiy komponent (Spring Framework asosidagi ilovalar uchun) 10 - ma'lumotlar bazasini aniqlash 12 - yaratilgan ma'lumotlar bazasi nomini o'rnatish 17 - bizning holatimiz uchun konfiguratsiyalarni chiqarib tashlash 19 - Builder naqshidan foydalanib ma'lumotlar bazasini yaratish ( Naqshning yaxshi umumiy ko'rinishi ) Va nihoyat, barcha shov-shuvlar ko'tarilayotgan ma'lumotlar bazasi bilan aloqa qilish uchun JdbcTemplate loviyasidir. G'oya shundan iboratki, bizda Tao testlari uchun asosiy sinf bo'ladi, undan barcha Tao test sinflari meros qilib olinadi, ularning vazifalariga quyidagilar kiradi:
  1. asosiy ma'lumotlar bazasida ishlatiladigan ba'zi skriptlarni ishga tushirish (jadvallar yaratish, ustunlarni o'zgartirish va boshqalar uchun skriptlar);
  2. jadvallarni test ma'lumotlari bilan to'ldiradigan test skriptlarini ishga tushirish;
  3. jadvallarni o'chirish.
@SpringBootTest(classes = TestConfigDB.class)
public abstract class DataBaseIT {

   @Autowired
   private JdbcTemplate jdbcTemplate;

   public JdbcTemplate getJdbcTemplate() {
       return jdbcTemplate;
   }

   public void fillDataBase(String[] initList) {
       for (String x : initList) {
           try {
               jdbcTemplate.update(IOUtils.resourceToString("/db.migrations/" + x, StandardCharsets.UTF_8));
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }

   public void cleanDataBase() {
       getJdbcTemplate().update("DROP database testDB");
       getJdbcTemplate().update("CREATE database testDB");
       getJdbcTemplate().update("USE testDB");
   }

   public void fillTables(String[] fillList) {
       for (String x : fillList) {
           try {
               Stream.of(
                       IOUtils.resourceToString("/fill_scripts/" + x, StandardCharsets.UTF_8))
                       .forEach(jdbcTemplate::update);
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }
}
1 - @SpringBootTest annotatsiyasidan foydalanib, biz test konfiguratsiyasini o'rnatdik 11 - bu usulda argument sifatida biz kerakli jadvallarning nomlarini beramiz va u mas'uliyatli mehnatkash sifatida ularni biz uchun yuklaydi (bu bizga imkoniyat beradi) bu usulni yuragimiz xohlagancha qayta ishlatish) 21 - biz ushbu usulni tozalash uchun foydalanamiz, ya'ni ma'lumotlar bazasidan barcha jadvallarni (va ularning ma'lumotlarini) o'chirish 27 - bu usuldagi argument test ma'lumotlari bilan skriptlar nomlari qatoridir. Bu ma'lum bir usulni sinab ko'rish uchun yuklanadi. Sinov ma'lumotlari bilan bizning skriptimiz:
INSERT INTO robots(name, cpu, producer)
VALUES ('Rex', 'Intel Core i5-9400F', 'Vietnam'),
      ('Molly', 'AMD Ryzen 7 2700X', 'China'),
      ('Ross', 'Intel Core i7-9700K', 'Malaysia')
Va endi biz bugun nima yig'dik.

Tao test klassi

@RunWith(SpringRunner.class)
public class RobotDataBaseIT extends DataBaseIT {

   private static RobotDAO countryDAO;

   @Before
   public void fillData() {
       fillDataBase(new String[]{
               "create_table_robots.sql"
       });
       countryDAO = new RobotDAOImpl(getJdbcTemplate());
   }

   @After
   public void clean() {
       cleanDataBase();
   }

   private RowMapper<Robot> robotMapper() {
       return (rs, rowNum) ->
               Robot.builder()
                       .id(rs.getLong("id"))
                       .name(rs.getString("name"))
                       .cpu(rs.getString("cpu"))
                       .producer(rs.getString("producer"))
                       .build();
   }
2 - testlarimiz uchun asosiy sinfdan meros bo'lamiz 4 - sinovdan o'tgan omborimiz 7 - har bir testdan oldin ishga tushiriladigan usul 8 - kerakli jadvallarni yuklash uchun ota-klass usulidan foydalanamiz 11 - dao 15 ni ishga tushiramiz - usul Bu har bir sinovdan so'ng ishga tushiriladi, ma'lumotlar bazasini tozalaydi 19 - Tao sinfiga o'xshash RowMapper dasturini amalga oshirish Biz bir sinov usulidan oldin va keyin ishlatiladigan @Before va @After dan foydalanamiz, lekin biz bizga ruxsat beruvchi ba'zi lib-ni olishimiz mumkin. ushbu toifadagi testlarning boshiga va oxiriga bog'langan izohlardan foydalanish. Misol uchun, bu testlarni sezilarli darajada tezlashtiradi, chunki jadvallar har safar va har bir sinfda bir marta yaratilishi va butunlay o'chirilishi kerak edi. Lekin biz buni qilmaymiz. Nega, deb so'rayapsizmi? Agar usullardan biri jadval tuzilishini o'zgartirsa-chi? Masalan, bitta ustunni o'chiring. Bunday holda, qolgan usullar muvaffaqiyatsiz bo'lishi mumkin yoki kutilganidek javob berishi kerak (masalan, orqa ustunni yaratish). Tan olishimiz kerakki, bu bizga testlarning bir-biriga keraksiz bog'lanishini (qaramligini) beradi, bu bizga hech qanday foyda keltirmaydi. Ammo men chekinaman, keling, davom etaylik ...

findById usulini sinab ko'rish

@Test
public void findByIdTest() {
   fillTables(new String[]{"fill_table_robots.sql"});

   Long id = getJdbcTemplate().queryForObject("SELECT id FROM robots WHERE name = 'Molly'", Long.class);
   Robot robot = countryDAO.findById(id);

   assertThat(robot).isNotNull();
   assertThat(robot.getId()).isEqualTo(id);
   assertThat(robot.getName()).isEqualTo("Molly");
   assertThat(robot.getCpu()).isEqualTo("AMD Ryzen 7 2700X");
   assertThat(robot.getProducer()).isEqualTo("China");
}
3 - jadvalni test ma'lumotlari bilan to'ldirish 5 - bizga kerak bo'lgan ob'ekt identifikatorini olish 6 - tekshirilayotgan usuldan foydalanish 8...12 - olingan ma'lumotlarni kutilganlar bilan solishtirish

Sinov usulini yangilash

@Test
public void updateTest() {
   fillTables(new String[]{"fill_table_robots.sql"});

   Long robotId = getJdbcTemplate().queryForObject("SELECT id FROM robots WHERE name = 'Rex'", Long.class);

   Robot updateRobot = Robot.builder()
           .id(robotId)
           .name("Aslan")
           .cpu("Intel Core i5-3470")
           .producer("Narnia")
           .build();

   Robot responseRobot = countryDAO.update(updateRobot);
   Robot updatedRobot = getJdbcTemplate().queryForObject(
           "SELECT id, name, cpu, producer FROM robots WHERE id = ?",
           robotMapper(),
           robotId);

   assertThat(updatedRobot).isNotNull();
   assertThat(updateRobot.getName()).isEqualTo(responseRobot.getName());
   assertThat(updateRobot.getName()).isEqualTo(updatedRobot.getName());
   assertThat(updateRobot.getCpu()).isEqualTo(responseRobot.getCpu());
   assertThat(updateRobot.getCpu()).isEqualTo(updatedRobot.getCpu());
   assertThat(updateRobot.getProducer()).isEqualTo(responseRobot.getProducer());
   assertThat(updateRobot.getProducer()).isEqualTo(updatedRobot.getProducer());
   assertThat(responseRobot.getId()).isEqualTo(updatedRobot.getId());
   assertThat(updateRobot.getId()).isEqualTo(updatedRobot.getId());
}
3 - jadvalni test ma'lumotlari bilan to'ldirish 5 - yangilanayotgan ob'ekt identifikatorini olish 7 - yangilangan ob'ektni qurish 14 - sinovdan o'tkazilayotgan usuldan foydalanish 15 - tekshirish uchun yangilangan ob'ektni olish 20...28 - olingan ma'lumotlarni solishtirish. kutilganlar Yangilash usulini sinab ko'rish yaratishga o'xshaydi. Hech bo'lmaganda men uchun. Siz yarashuvlarni xohlaganingizcha burishingiz mumkin: hech qachon juda ko'p tekshiruvlar bo'lishi mumkin emas. Shuni ham ta'kidlashni istardimki, testlar to'liq funksionallikni yoki xatolarning yo'qligini kafolatlamaydi. Sinovlar faqat dasturning haqiqiy natijasi (uning bo'lagi) kutilgan natijaga mos kelishini ta'minlaydi. Bunday holda, faqat testlar yozilgan qismlar tekshiriladi.

Testlar bilan dars boshlaymiz...

MySql - 7 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinoviG'alaba)) Keling, choy qaynatamiz va pechenye olamiz: biz bunga loyiqmiz)) MySql - 8 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinovi

foydali havolalar

O'qishni tugatganlar uchun, e'tiboringiz uchun rahmat va... MySql - 9 o'rniga MariaDB yordamida ma'lumotlar bazasini integratsiya sinovi

*yulduzli urushlar epik musiqasi*

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