JavaRush /Java Blog /Random-ID /Pengujian integrasi database menggunakan MariaDB untuk me...

Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql

Dipublikasikan di grup Random-ID
Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 1Hari ini saya ingin berbicara tentang pengujian, karena semakin banyak kode yang dicakup dalam pengujian, dianggap semakin baik dan andal. Mari kita bicara bukan tentang pengujian unit, tetapi tentang pengujian integrasi database. Apa sebenarnya perbedaan antara pengujian unit dan pengujian integrasi? Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 2Modular (unit) adalah pengujian program pada tingkat modul, metode, atau kelas individual, yaitu pengujian yang cepat dan mudah, memengaruhi bagian fungsionalitas yang paling dapat dibagi. Mereka juga disebut sebagai “satu tes per metode”. Integrasi lebih lambat dan lebih berat, dan dapat terdiri dari beberapa modul dan fungsionalitas tambahan. Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 3Mengapa pengujian untuk integrasi lapisan dao (Objek Akses Data) merupakan pengujian? Karena untuk menguji metode dengan query ke database, kita perlu membuat database terpisah di RAM, menggantikan database utama. Idenya adalah kita membuat tabel yang kita perlukan, mengisinya dengan data pengujian dan memeriksa kebenaran metode kelas repositori (bagaimanapun juga, kita tahu apa hasil akhirnya dalam kasus tertentu). Jadi, mari kita mulai. Topik tentang menghubungkan database telah lama dibahas secara luas, dan oleh karena itu hari ini saya tidak ingin membahas hal ini, dan kami hanya akan mempertimbangkan bagian dari program yang kami minati. Secara default, kita akan mulai dari fakta bahwa aplikasi kita didasarkan pada Spring Boot, untuk lapisan dao Spring JDBC (untuk lebih jelasnya), database utama kita adalah MySQL, dan kita akan menggantinya menggunakan MariaDB (kompatibel secara maksimal, dan karenanya skrip MySQL tidak akan pernah ada konflik dengan dialek MariaDB, seperti halnya dengan H2). Kami juga akan berasumsi secara kondisional bahwa program kami menggunakan Liquibase untuk mengelola dan menerapkan perubahan pada skema database, dan karenanya, semua skrip yang diterapkan disimpan dalam aplikasi kami.

Struktur proyek

Hanya bagian yang terpengaruh yang ditampilkan: Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 5Dan ya, hari ini kita akan membuat robot)) Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 6Skrip untuk tabel, metode yang akan kita uji hari ini (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;
Entitas yang mewakili tabel ini:
@Builder
@Data
public class Robot {

   private Long id;

   private String name;

   private String cpu;

   private String producer;
}
Antarmuka untuk repositori yang diuji:
public interface RobotDAO {

   Robot findById(Long id);

   Robot create(Robot robot);

   List<Robot> findAll();

   Robot update(Robot robot);

   void delete(Long id);
}
Sebenarnya, berikut adalah operasi CRUD standar, tanpa eksotik, jadi kami tidak akan mempertimbangkan penerapan semua metode (yah, ini tidak akan mengejutkan siapa pun), tetapi beberapa - agar lebih singkat:
@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();
   }
Mari kita melakukan sedikit penyimpangan dan melihat apa yang terjadi dengan dependensi kita (hanya yang digunakan untuk bagian aplikasi yang didemonstrasikan yang disajikan):
<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 - ketergantungan untuk database MariaDb itu sendiri 10 - ketergantungan untuk menghubungkan dengan SpringBoot 16 - Lombok (yah, saya rasa semua orang tahu jenis lib apa ini) 22 - starter untuk pengujian (di mana JUnit yang kita perlukan tertanam) 28 - starter untuk bekerja dengan springJdbc Mari kita lihat wadah Spring dengan kacang yang diperlukan untuk pengujian kita (khususnya, kacang pembuatan MariaDB):
@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 - komponen utama untuk membesarkan MariaDB (untuk aplikasi berdasarkan Spring Framework) 10 - mendefinisikan kacang database 12 - mengatur nama Database yang dibuat 17 - mengeluarkan konfigurasi untuk kasus kita 19 - membangun database menggunakan pola Builder ( gambaran umum yang bagus tentang polanya ) Dan terakhir, yang menjadi keributan adalah kacang JdbcTemplate untuk komunikasi dengan database yang sedang dimunculkan. Idenya adalah kita akan memiliki kelas utama untuk tes Tao, yang darinya semua kelas tes Tao akan mewarisi, yang tugasnya meliputi:
  1. meluncurkan beberapa script yang digunakan pada database utama (script untuk membuat tabel, mengubah kolom, dan lain-lain);
  2. meluncurkan skrip pengujian yang mengisi tabel dengan data pengujian;
  3. menghapus tabel.
@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 - menggunakan anotasi @SpringBootTest kami menetapkan konfigurasi pengujian 11 - sebagai argumen dalam metode ini kami meneruskan nama tabel yang kami perlukan, dan dia, sebagai pekerja keras yang bertanggung jawab, akan memuatnya untuk kami (yang memberi kami kesempatan untuk menggunakan kembali metode ini sebanyak yang diinginkan hati kita) 21 - kita menggunakan metode ini untuk pembersihan, yaitu menghapus semua tabel (dan datanya) dari database 27 - argumen dalam metode ini adalah array nama skrip dengan data pengujian yang akan dimuat untuk menguji metode tertentu. Skrip kami dengan data pengujian:
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')
Dan sekarang apa yang telah kita kumpulkan hari ini.

Kelas pengujian Tao

@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 - kami mewarisi dari kelas utama untuk pengujian kami 4 - repositori kami yang diuji 7 - metode yang akan diluncurkan sebelum setiap pengujian 8 - kami menggunakan metode kelas induk untuk memuat tabel yang diperlukan 11 - kami menginisialisasi dao kami 15 - sebuah metode yang akan diluncurkan setelah setiap pengujian, membersihkan database kami 19 - implementasi RowMapper kami, analog dengan kelas Tao Kami menggunakan @Before dan @After, yang digunakan sebelum dan sesudah satu metode pengujian, tetapi kami dapat menggunakan beberapa lib yang memungkinkan kami untuk menggunakan anotasi yang terkait dengan awal tes eksekusi kelas ini dan akhir. Misalnya, yang satu ini , yang akan mempercepat pengujian secara signifikan, karena tabel harus dibuat dan dihapus seluruhnya setiap saat, dan satu kali per kelas. Tapi kami tidak melakukan itu. Mengapa kamu bertanya? Bagaimana jika salah satu metode mengubah struktur tabel? Misalnya, hapus satu kolom. Dalam kasus ini, metode lainnya mungkin gagal atau harus merespons seperti yang diharapkan (misalnya, membuat kolom kembali). Kita harus mengakui bahwa ini memberi kita koneksi (ketergantungan) pengujian yang tidak perlu satu sama lain, yang tidak ada gunanya bagi kita. Tapi saya ngelantur, ayo lanjutkan...

Menguji metode findById

@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 - isi tabel dengan data uji 5 - dapatkan id untuk entitas yang kita butuhkan 6 - gunakan metode yang sedang diuji 8...12 - bandingkan data yang diterima dengan yang diharapkan

Perbarui tes metode

@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 - mengisi tabel dengan data uji 5 - mendapatkan id entitas yang sedang diperbarui 7 - membangun entitas yang diperbarui 14 - menggunakan metode yang sedang diuji 15 - mendapatkan entitas yang diperbarui untuk verifikasi 20...28 - membandingkan data yang diterima dengan yang diharapkan Menguji metode pembaruan mirip dengan membuat. Setidaknya untuk saya. Anda dapat memutarbalikkan rekonsiliasi sebanyak yang Anda suka: pemeriksaan tidak akan pernah terlalu banyak. Saya juga ingin mencatat bahwa pengujian tidak menjamin fungsionalitas penuh atau tidak adanya bug. Pengujian hanya memastikan bahwa hasil aktual dari program (fragmennya) sesuai dengan yang diharapkan. Dalam hal ini, hanya bagian-bagian yang tesnya ditulis yang diperiksa.

Mari kita luncurkan kelas dengan tes...

Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 7Kemenangan)) Ayo buat teh dan ambil kue: kita pantas mendapatkannya)) Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 8

tautan yang bermanfaat

Bagi yang sudah selesai membaca, terima kasih atas perhatian dan... Pengujian integrasi database menggunakan MariaDB untuk menggantikan MySql - 9

*musik Star Wars yang epik*

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