JavaRush /Blog Java /Random-VI /Kiểm tra tích hợp cơ sở dữ liệu bằng MariaDB để thay thế ...

Kiểm tra tích hợp cơ sở dữ liệu bằng MariaDB để thay thế MySql

Xuất bản trong nhóm
Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 1Hôm nay tôi muốn nói về thử nghiệm, bởi vì mã càng được kiểm tra nhiều thì mã càng được coi là tốt hơn và đáng tin cậy hơn. Chúng ta không nói về thử nghiệm đơn vị mà là về thử nghiệm tích hợp cơ sở dữ liệu. Chính xác thì sự khác biệt giữa bài kiểm tra đơn vị và bài kiểm tra tích hợp là gì? Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 2Mô-đun (đơn vị) đang thử nghiệm một chương trình ở cấp độ các mô-đun, phương thức hoặc lớp riêng lẻ, nghĩa là các thử nghiệm diễn ra nhanh chóng và dễ dàng, ảnh hưởng đến các phần dễ phân chia nhất của chức năng. Chúng còn được gọi là “một thử nghiệm cho mỗi phương pháp”. Những cái tích hợp chậm hơn và nặng hơn và có thể bao gồm một số mô-đun và chức năng bổ sung. Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 3Tại sao phải kiểm tra các bài kiểm tra tích hợp lớp dao (Đối tượng truy cập dữ liệu)? Bởi vì để kiểm tra các phương thức truy vấn cơ sở dữ liệu, chúng ta cần tạo một cơ sở dữ liệu riêng trong RAM, thay thế cơ sở dữ liệu chính. Ý tưởng là chúng tôi tạo các bảng mà chúng tôi cần, điền dữ liệu thử nghiệm vào chúng và kiểm tra tính chính xác của các phương thức lớp kho lưu trữ (xét cho cùng, chúng tôi biết kết quả cuối cùng sẽ như thế nào trong một trường hợp nhất định). Vì vậy, hãy bắt đầu. Các chủ đề về kết nối cơ sở dữ liệu từ lâu đã được đề cập rất rộng rãi, và do đó hôm nay tôi không muốn đề cập đến vấn đề này và chúng tôi sẽ chỉ xem xét các phần của chương trình mà chúng tôi quan tâm. Theo mặc định, chúng tôi sẽ bắt đầu từ thực tế là ứng dụng của chúng tôi dựa trên Spring Boot, đối với lớp dao Spring JDBC (để rõ ràng hơn), cơ sở dữ liệu chính của chúng tôi là MySQL và chúng tôi sẽ thay thế nó bằng MariaDB (chúng tương thích tối đa và do đó, các tập lệnh MySQL sẽ không bao giờ có xung đột với phương ngữ MariaDB, như sẽ xảy ra với H2). Chúng tôi cũng sẽ giả định một cách có điều kiện rằng chương trình của chúng tôi sử dụng Liquibase để quản lý và áp dụng các thay đổi đối với lược đồ cơ sở dữ liệu và theo đó, tất cả các tập lệnh được áp dụng đều được lưu trữ trong ứng dụng của chúng tôi.

Cấu trúc dự án

Chỉ những phần bị ảnh hưởng mới được hiển thị: Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 5Và vâng, hôm nay chúng tôi sẽ tạo rô-bốt)) Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 6Tập lệnh cho bảng, các phương thức mà chúng tôi sẽ kiểm tra hôm nay (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;
Thực thể đại diện cho bảng này:
@Builder
@Data
public class Robot {

   private Long id;

   private String name;

   private String cpu;

   private String producer;
}
Giao diện cho kho lưu trữ được thử nghiệm:
public interface RobotDAO {

   Robot findById(Long id);

   Robot create(Robot robot);

   List<Robot> findAll();

   Robot update(Robot robot);

   void delete(Long id);
}
Trên thực tế, đây là các hoạt động CRUD tiêu chuẩn, không có ngoại lệ, vì vậy chúng tôi sẽ xem xét việc triển khai không phải tất cả các phương pháp (à, điều này sẽ không làm ai ngạc nhiên), nhưng một số - để ngắn gọn hơ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();
   }
Chúng ta hãy lạc đề một chút và xem điều gì đang xảy ra với các phần phụ thuộc của chúng ta (chỉ những phần được sử dụng cho phần trình diễn của ứng dụng mới được trình bày):
<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 - phần phụ thuộc vào chính cơ sở dữ liệu MariaDb 10 - phần phụ thuộc để kết nối với SpringBoot 16 - Lombok (à, tôi nghĩ mọi người đều biết đây là loại lib nào) 22 - phần khởi động cho các bài kiểm tra (trong đó JUnit chúng tôi cần được nhúng) 28 - phần khởi động cho làm việc với springJdbc Chúng ta hãy xem Spring container với các loại đậu cần thiết cho các thử nghiệm của chúng tôi (đặc biệt là đậu tạo 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 - thành phần chính để nâng cao MariaDB (dành cho các ứng dụng dựa trên Spring Framework) 10 - xác định một cơ sở dữ liệu 12 - đặt tên của Cơ sở dữ liệu đã tạo 17 - lấy ra các cấu hình cho trường hợp của chúng ta 19 - xây dựng cơ sở dữ liệu bằng mẫu Builder ( một cái nhìn tổng quan hay về mẫu ) Và cuối cùng, điều gây ồn ào nhất là đậu JdbcTemplate để liên lạc với cơ sở dữ liệu đang được nâng lên. Ý tưởng là chúng ta sẽ có một lớp chính cho các bài kiểm tra Đạo, từ đó tất cả các lớp kiểm tra Đạo sẽ kế thừa, có nhiệm vụ bao gồm:
  1. khởi chạy một số tập lệnh được sử dụng trong cơ sở dữ liệu chính (tập lệnh để tạo bảng, thay đổi cột và các tập lệnh khác);
  2. khởi chạy các tập lệnh kiểm tra để điền vào các bảng dữ liệu kiểm tra;
  3. xóa các bảng.
@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 - bằng cách sử dụng chú thích @SpringBootTest, chúng tôi đặt cấu hình thử nghiệm 11 - làm đối số trong phương thức này, chúng tôi chuyển tên của các bảng mà chúng tôi cần và anh ấy, với tư cách là một nhân viên chăm chỉ có trách nhiệm, sẽ tải chúng cho chúng tôi (điều này mang lại cho chúng tôi cơ hội để sử dụng lại phương pháp này nhiều như trái tim chúng ta mong muốn) 21 - chúng tôi sử dụng phương pháp này để dọn dẹp, cụ thể là xóa tất cả các bảng (và dữ liệu của chúng) khỏi cơ sở dữ liệu 27 - đối số trong phương thức này là một mảng tên của các tập lệnh có dữ liệu thử nghiệm sẽ được tải để thử nghiệm một phương pháp cụ thể.Kịch bản của chúng tôi với dữ liệu thử nghiệm:
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')
Và bây giờ là những gì chúng ta đã tập hợp cho ngày hôm nay.

Lớp kiểm tra đạo

@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 - chúng tôi kế thừa từ lớp chính cho các thử nghiệm của mình 4 - kho lưu trữ đã thử nghiệm của chúng tôi 7 - một phương thức sẽ được khởi chạy trước mỗi thử nghiệm 8 - chúng tôi sử dụng phương thức lớp cha để tải các bảng cần thiết 11 - chúng tôi khởi tạo dao 15 - một phương thức sẽ được khởi chạy sau mỗi lần kiểm tra, làm sạch cơ sở dữ liệu của chúng tôi 19 - triển khai RowMapper của chúng tôi, tương tự như lớp Tao. Chúng tôi sử dụng @Before và @After, được sử dụng trước và sau một phương pháp kiểm tra, nhưng chúng tôi có thể sử dụng một số lib cho phép chúng tôi để sử dụng các chú thích được gắn với phần đầu và phần cuối của các bài kiểm tra thực thi của lớp này. Ví dụ: cái này sẽ tăng tốc đáng kể các bài kiểm tra, vì các bảng sẽ phải được tạo và xóa hoàn toàn mỗi lần và một lần cho mỗi lớp. Nhưng chúng tôi không làm điều đó. Lý do tại sao bạn hỏi? Điều gì sẽ xảy ra nếu một trong các phương thức thay đổi cấu trúc của bảng? Ví dụ: xóa một cột. Trong trường hợp này, các phương pháp còn lại có thể không thành công hoặc phải phản hồi như mong đợi (ví dụ: tạo cột quay lại). Chúng tôi phải thừa nhận rằng điều này mang lại cho chúng tôi sự kết nối (sự phụ thuộc) không cần thiết của các bài kiểm tra với nhau, điều này không có ích gì đối với chúng tôi. Nhưng tôi lạc đề rồi, hãy tiếp tục...

Kiểm tra phương pháp 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 - điền dữ liệu thử nghiệm vào bảng 5 - lấy id cho thực thể chúng ta cần 6 - sử dụng phương pháp đang được thử nghiệm 8...12 - so sánh dữ liệu nhận được với dữ liệu dự kiến

Cập nhật phương pháp kiểm tra

@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 - điền vào bảng dữ liệu thử nghiệm 5 - lấy id của thực thể đang được cập nhật 7 - xây dựng thực thể được cập nhật 14 - sử dụng phương pháp đang được thử nghiệm 15 - lấy thực thể được cập nhật để xác minh 20...28 - so sánh dữ liệu nhận được với những cái được mong đợi Kiểm tra phương pháp cập nhật cũng tương tự như tạo. Ít nhất là đối với tôi. Bạn có thể điều chỉnh việc đối chiếu bao nhiêu tùy thích: không bao giờ có quá nhiều lần kiểm tra. Tôi cũng muốn lưu ý rằng các bài kiểm tra không đảm bảo đầy đủ chức năng hoặc không có lỗi. Các thử nghiệm chỉ đảm bảo rằng kết quả thực tế của chương trình (đoạn của nó) tương ứng với kết quả mong đợi. Trong trường hợp này, chỉ những phần đã viết bài kiểm tra mới được kiểm tra.

Hãy bắt đầu một lớp học với các bài kiểm tra...

Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 7Chiến thắng)) Cùng đi pha trà và ăn bánh quy: chúng ta xứng đáng mà)) Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 8

Liên kết hữu ích

Những ai đã đọc xong xin cảm ơn sự quan tâm và... Kiểm thử tích hợp cơ sở dữ liệu sử dụng MariaDB thay thế MySql - 9

*nhạc Star Wars hoành tráng*

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION