JavaRush /Java Blogu /Random-AZ /MySql-i əvəz etmək üçün MariaDB istifadə edərək verilənlə...

MySql-i əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya sınağı

Qrupda dərc edilmişdir
MySql-i əvəz etmək üçün MariaDB-dən istifadə edərək verilənlər bazasının inteqrasiya sınağı - 1Bu gün test haqqında danışmaq istərdim, çünki kod nə qədər çox testlərlə əhatə olunsa, bir o qədər yaxşı və etibarlı hesab olunur. Gəlin vahid testdən deyil, verilənlər bazalarının inteqrasiya testindən danışaq. Vahid testləri ilə inteqrasiya testləri arasında dəqiq fərq nədir? MySql - 2-ni əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya testiModul (vahid) proqramı fərdi modullar, metodlar və ya siniflər səviyyəsində sınaqdan keçirir, yəni testlər sürətli və asan olur, funksionallığın ən bölünən hissələrinə təsir göstərir. Onlara "hər bir üsul üçün bir test" də deyilir. İnteqrasiya daha yavaş və daha ağırdır və bir neçə moduldan və əlavə funksionallıqdan ibarət ola bilər. MySql - 3-ü əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya testiNiyə testlər dao (Data Access Object) təbəqəsi inteqrasiya testləridir? Çünki verilənlər bazasına sorğularla metodları sınaqdan keçirmək üçün biz RAM-da əsası əvəz edərək ayrıca verilənlər bazası yaratmalıyıq. İdeya ondan ibarətdir ki, biz bizə lazım olan cədvəlləri yaradırıq, onları test məlumatları ilə doldururuq və repozitor sinfi metodlarının düzgünlüyünü yoxlayırıq (hər şeydən sonra, müəyyən bir vəziyyətdə son nəticənin nə olacağını bilirik). Beləliklə, başlayaq. Verilənlər bazasını birləşdirən mövzular çoxdan geniş şəkildə əhatə olunmuşdur və buna görə də bu gün bu barədə danışmaq istəməzdim və proqramın yalnız bizi maraqlandıran hissələrini nəzərdən keçirəcəyik. Varsayılan olaraq, tətbiqimizin Spring Boot-a əsaslandığından başlayacağıq, Spring JDBC dao təbəqəsi üçün (daha aydınlıq üçün), əsas verilənlər bazamız MySQL-dir və biz onu MariaDB istifadə edərək əvəz edəcəyik (onlar maksimum uyğundur və müvafiq olaraq MySQL skriptlərində heç vaxt MariaDB dialekti ilə heç bir ziddiyyət olmayacaq, H2 ilə olduğu kimi). Biz həmçinin şərti olaraq güman edəcəyik ki, proqramımız verilənlər bazası sxeminə dəyişiklikləri idarə etmək və tətbiq etmək üçün Liquibase-dən istifadə edir və müvafiq olaraq bütün tətbiq olunan skriptlər tətbiqimizdə saxlanılır.

Layihə strukturu

Yalnız təsirlənmiş hissələr göstərilir: MySql - 5-i əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya testiBəli, bu gün biz robotlar yaradacağıq)) MySql - 6-nı əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya testiCədvəl üçün skript, bu gün sınaqdan keçirəcəyimiz üsullar (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;
Bu cədvəli təmsil edən qurum:
@Builder
@Data
public class Robot {

   private Long id;

   private String name;

   private String cpu;

   private String producer;
}
Test edilmiş repozitoriya üçün interfeys:
public interface RobotDAO {

   Robot findById(Long id);

   Robot create(Robot robot);

   List<Robot> findAll();

   Robot update(Robot robot);

   void delete(Long id);
}
Əslində, burada ekzotik olmayan standart CRUD əməliyyatları var, buna görə də bütün metodların deyil (yaxşı, bu heç kimi təəccübləndirməyəcək), lakin bəzilərinin həyata keçirilməsini nəzərdən keçirəcəyik - daha çox qısalıq üçün:
@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();
   }
Gəlin bir az kənara çıxaq və asılılıqlarımızla nə baş verdiyini görək (yalnız tətbiqin nümayiş olunan hissəsi üçün istifadə olunanlar təqdim olunur):
<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 verilənlər bazasının özündən asılılıq 10 - SpringBoot ilə əlaqə üçün asılılıq 16 - Lombok (yaxşı, məncə bunun nə cür lib olduğunu hamı bilir) 22 - testlər üçün başlanğıc (bizə lazım olan JUnit quraşdırılıb) 28 - başlanğıc üçün springJdbc ilə işləmək Gəlin sınaqlarımız üçün lazım olan paxlalı Bahar qabına nəzər salaq (xüsusən, MariaDB yaradılması paxlası):
@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-nin artırılması üçün əsas komponent (Bahar Çərçivəsinə əsaslanan proqramlar üçün) 10 - verilənlər bazası lobyasının təyin edilməsi 12 - yaradılmış verilənlər bazasının adının təyin edilməsi 17 - işimiz üçün konfiqurasiyaların çıxarılması 19 - Builder nümunəsindən istifadə edərək verilənlər bazası qurulması ( Nümunənin yaxşı icmalı ) Və nəhayət, bütün təlaş, qaldırılan verilənlər bazası ilə əlaqə üçün JdbcTemplate paxlasıdır. İdeya ondan ibarətdir ki, Tao testləri üçün əsas sinifimiz olacaq, bütün Tao test sinifləri ondan miras qalacaq, tapşırıqlarına aşağıdakılar daxildir:
  1. əsas verilənlər bazasında istifadə olunan bəzi skriptlərin işə salınması (cədvəllərin yaradılması, sütunların dəyişdirilməsi və s. üçün skriptlər);
  2. cədvəlləri test məlumatları ilə dolduran test skriptlərinin işə salınması;
  3. cədvəllərin silinməsi.
@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 annotasiyasından istifadə edərək test konfiqurasiyasını təyin etdik 11 - bu üsulda arqument olaraq ehtiyac duyduğumuz cədvəllərin adlarını veririk və o, məsuliyyətli bir zəhmətkeş kimi onları bizim üçün yükləyəcək (bu bizə imkan verir ürəyimiz istədiyi qədər bu metoddan təkrar istifadə etmək) 21 - biz bu üsuldan təmizləmək üçün istifadə edirik, yəni bütün cədvəlləri (və onların məlumatlarını) verilənlər bazasından silmək 27 - bu üsuldakı arqument test məlumatları olan skript adlarının massividir. xüsusi metodu sınaqdan keçirmək üçün yüklənəcək. Test datası olan 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')
İndi hamımız bu gün üçün nə topladıq.

Tao test sinfi

@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 - testlərimiz üçün əsas sinifdən miras alırıq 4 - sınaqdan keçirilmiş repozitorumuz 7 - hər testdən əvvəl işə salınacaq metod 8 - lazımi cədvəlləri yükləmək üçün ana sinif metodundan istifadə edirik 11 - dao 15-imizi işə salırıq - metod hər testdən sonra işə salınacaq, verilənlər bazamızı təmizləyəcək 19 - Tao sinifinə bənzər RowMapper-imizin tətbiqi Biz bir sınaq metodundan əvvəl və sonra istifadə olunan @Before və @After istifadə edirik, lakin bizə imkan verən bəzi lib götürə bilərik. bu sinfin icra testlərinin əvvəlinə və sonuna bağlı annotasiyalardan istifadə etmək. Məsələn, bu , testləri əhəmiyyətli dərəcədə sürətləndirəcək, çünki cədvəllər hər dəfə və hər sinifdə bir dəfə yaradılmalı və tamamilə silinməlidir. Amma biz bunu etmirik. Niyə, soruşursan? Metodlardan biri cədvəlin strukturunu dəyişdirsə nə olar? Məsələn, bir sütunu silin. Bu halda, qalan üsullar ya uğursuz ola bilər, ya da gözlənildiyi kimi cavab verməlidir (məsələn, arxa sütun yaradın). Etiraf etməliyik ki, bu bizə testlərin bir-birimizdən lazımsız əlaqəsini (asılılığını) verir, bunun bizə heç bir faydası yoxdur. Ancaq qaçıram, davam edək...

findById metodunun sınaqdan keçirilməsi

@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 - cədvəli test məlumatları ilə doldurun 5 - bizə lazım olan obyektin id-sini əldə edin 6 - sınaqdan keçirilən metoddan istifadə edin 8...12 - alınan məlumatları gözlənilənlərlə müqayisə edin

Metod testini yeniləyin

@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 - cədvəli test məlumatları ilə doldurun 5 - yenilənən obyektin id-sini əldə edin 7 - yenilənmiş obyekti qurun 14 - sınaqdan keçirilən metoddan istifadə edin 15 - yoxlama üçün yenilənmiş obyekti alın 20...28 - alınan məlumatları gözlənilənlər Yeniləmə metodunun sınaqdan keçirilməsi yaratmağa bənzəyir. Ən azından mənim üçün. İstədiyiniz qədər uzlaşmaları bükə bilərsiniz: heç vaxt çox çek ola bilməz. Onu da qeyd etmək istərdim ki, testlər tam funksionallıq və ya səhvlərin olmamasına zəmanət vermir. Testlər yalnız proqramın faktiki nəticəsinin (onun fraqmentinin) gözlənilən nəticəyə uyğun olmasını təmin edir. Bu halda, yalnız testlərin yazıldığı hissələr yoxlanılır.

Testlərlə dərsə başlayaq...

MySql - 7-ni əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya sınağıQələbə)) Gedək çay dəmləyib peçenye götürək: biz buna layiqik)) MySql - 8-i əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya sınağı

faydalı bağlantılar

Oxuyub bitirənlər üçün, diqqətinizə və... MySql - 9-u əvəz etmək üçün MariaDB istifadə edərək verilənlər bazasının inteqrasiya sınağı

*epik Star Wars musiqisi*

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION