Viết Unit Test cho Spring Boot application

Testing Thực hành

Khi làm việc với các ứng dụng sử dụng Spring Boot, các bạn sẽ cần phải viết Unit Test cho những đoạn code của mình. Trong bài viết này, mình sẽ hướng dẫn các bạn cách viết Unit Test cho Spring Boot application các bạn nhé!

Đầu tiên, mình sẽ tạo mới một ứng dụng Spring Boot đơn giản để làm ví dụ:

Viết Unit Test cho Spring Boot application

Ứng dụng này chỉ làm nhiệm vụ đơn giản là in một message ra console với nội dung “Hello Khanh. Total of 2 and 3 is 5”. Để làm được điều này, ứng dụng của chúng ta sẽ có 2 class được khai báo trong Spring container với nội dung như sau:

Class Hello:

package com.huongdanjava.springboot;

import org.springframework.stereotype.Component;

@Component
public class Hello {

  public String say(String name) {
    return "Hello " + name;
  }
}Code language: JavaScript (javascript)

Class này định nghĩa một method cho phép chúng ta truyền tên và nó sẽ return lại chuỗi “Hello” cộng với tên mà các bạn truyền vào.

Class Calculation:

package com.huongdanjava.springboot;

import org.springframework.stereotype.Service;

@Service
public class Calculation {

  public int sum(int a, int b) {
    return a + b;
  }
}Code language: PHP (php)

Class này cho phép chúng ta tính tổng của 2 số.

Kết quả khi chạy chương trình này sẽ như sau:

Viết Unit Test cho Spring Boot application

Ok, bây giờ chúng ta sẽ tiến hành viết code Unit Test cho ứng dụng này các bạn nhé!

Ý tưởng là chúng ta cần viết Unit Test để kiểm tra khi ứng dụng chạy, 2 bean của các class Hello và Calculation phải được khởi tạo trong Spring container và các method của chúng phải return đúng giá trị mà chúng ta mong muốn.

Để làm được điều này, trước tiên các bạn cần make sure là dependency của Spring Boot Test được khai báo trong trong tập tin pom.xml của các bạn. Của mình khi tạo Spring Boot project sử dụng Spring Tool Suite, nó đã được include như sau:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.junit.vintage</groupId>
      <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
  </exclusions>
</dependency>Code language: HTML, XML (xml)

Có thể các bạn sẽ thắc mắc tại sao mặc định khi tạo Spring Boot project, phần Spring Boot Starter Test này lại exclude thư viện junit-vintage-engine đi. Nguyên nhân là bởi vì junit-vintage-engine là cho JUnit 4 và JUnit 3, chúng ta nên sử dụng latest version của JUnit là JUnit 5. Với khai báo dependency cho JUnit 5 như sau:

<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-engine</artifactId>
  <scope>test</scope>
</dependency>Code language: HTML, XML (xml)

Để viết Unit Test cho Spring Boot application, các bạn chỉ cần khai báo trong class Test một Annotation của Spring Boot Test @SpringBootTest là xong. Ví dụ:

package com.huongdanjava.springboot;

import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class HelloTest {

}Code language: CSS (css)

Hay:

package com.huongdanjava.springboot;

import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class CalculationTest {

}Code language: CSS (css)

Class SpringBootUnitTestApplicationTests thì đã được thêm tự động rồi:

package com.huongdanjava.springboot;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringBootUnitTestApplicationTests {

  @Test
  void contextLoads() {
  }

}Code language: CSS (css)

Với annotation @SpringBootTest này, Spring Boot Test sẽ tự động chạy một Spring container và khởi tạo các bean trong Spring container này trong lúc chúng ta chạy test.

Bean của các class nào sẽ được khởi tạo trong Spring container tuỳ thuộc vào cấu hình của chúng ta.

Nếu các bạn khai báo thêm annotation @ContextConfiguration với value là các class chứa định nghĩa thông tin bean thì chỉ những bean được định nghĩa trong các class này mới được khởi tạo.

Nếu các bạn không khai báo thêm annotation @ContextConfiguration thì Spring Boot Test sẽ tự động scan những class nào được khai báo với annotation @Configuration và được sử dụng với annotation @SpringBootConfiguration để khởi tạo bean.

Trong ví dụ của mình thì mình đang sử dụng cơ chế auto component scan để khởi tạo bean trong Spring, không khai báo bean một cách tường minh nên những bean này là được sử dụng với annotation @SpringBootConfiguration để khởi tạo.

Các bạn có thể thêm code test để kiểm tra các bean của các class Hello và Calculation phải được khởi tạo trong class SpringBootUnitTestApplicationTests như sau:

package com.huongdanjava.springboot;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;

@SpringBootTest
class SpringBootUnitTestApplicationTests {

  @Autowired
  private ApplicationContext context;

  @Test
  public void testCalculation() {
    Assertions.assertTrue(context.getBean(Calculation.class) != null);
  }

  @Test
  public void testHello() {
    Assertions.assertTrue(context.getBean(Hello.class) != null);
  }

}Code language: JavaScript (javascript)

Test cho các class Hello và Calculation sẽ như sau:

package com.huongdanjava.springboot;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;

@SpringBootTest
public class CalculationTest {

  @Autowired
  private ApplicationContext context;

  @Test
  public void testSum() {
    Calculation calculation = context.getBean(Calculation.class);

    Assertions.assertEquals(9, calculation.sum(4, 5));
  }
}Code language: JavaScript (javascript)

Nếu các bạn chỉ muốn test class Hello, các bạn có thể tạo mới một class TestConfiguration với nội dung như sau:

package com.huongdanjava.springboot;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfiguration {

  @Bean
  public Hello hello() {
    return new Hello();
  }
}Code language: CSS (css)

Rồi sau đó sử dụng annotation @ContextConfiguration để khai báo class TestConfiguration này vào để viết test:

package com.huongdanjava.springboot;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;

@SpringBootTest
@ContextConfiguration(classes = { TestConfiguration.class })
public class Hello1Test {

  @Autowired
  private ApplicationContext context;

  @Test
  public void testSay() {
    Hello hello = context.getBean(Hello.class);

    Assertions.assertEquals("Hello Khanh", hello.say("Khanh"));
  }

}Code language: JavaScript (javascript)

Trong trường hợp này, các bạn sẽ không thể lấy bean của class Calculation. Ví dụ:

package com.huongdanjava.springboot;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;

@SpringBootTest
@ContextConfiguration(classes = { TestConfiguration.class })
public class Hello1Test {

  @Autowired
  private ApplicationContext context;

  @Test
  public void testSay() {
    Hello hello = context.getBean(Hello.class);

    Assertions.assertEquals("Hello Khanh", hello.say("Khanh"));
  }

  @Test
  public void testBeanConfiguration() {
    Calculation calculation = context.getBean(Calculation.class);
  }
}Code language: JavaScript (javascript)

Sẽ gặp lỗi ngay:

Viết Unit Test cho Spring Boot application

Nguồn: https://huongdanjava.com/vi/viet-unit-test-cho-spring-boot-application.html

Leave a Reply

Your email address will not be published. Required fields are marked *