Trong bài viết trước, chúng ta truyền đối tượng Mock vào class mà chúng ta đang viết Unit Test bằng cách sử dụng phương thức Setter của class này. Thế nhưng, trong trường hợp nếu các bạn đang sử dụng Spring framework trong ứng dụng của mình, các đối tượng phụ thuộc được inject vào đối tượng chúng ta đang viết Unit Test sử dụng annotation @Autowire, do vậy, chúng ta sẽ không có các phương thức Setter để truyền đối tượng Mock. Trong trường hợp này, các bạn có thể sử dụng annotation @InjectMocks của Mockito để làm được điều này. Cụ thể như thế nào? Chúng ta sẽ cùng nhau tìm hiểu trong bài viết này các bạn nhé!
Đầu tiên, mình sẽ tạo một Maven project:
với Spring framework, Mockito và JUnit dependencies như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.0</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>3.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> |
Với JUnit 5, để chạy được Unit Test với Maven, chúng ta cần khai báo plugin maven-surefire-plugin của Maven với latest version như sau:
1 2 3 4 5 6 7 8 |
<build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </build> |
Và compile source với target sử dụng Java 8 trở đi:
1 2 3 4 |
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> |
Trong ví dụ của bài viết này, mình sẽ tạo một ứng dụng nhỏ với một class Calculation định nghĩa một phương thức để tính hiệu của 2 số được khai báo với annotation @Component của Spring như sau:
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.huongdanjava.mockito; import org.springframework.stereotype.Component; @Component public class Calculation { public int sub(int a, int b) { return a - b; } } |
Và một class Application định nghĩa một method sử dụng phương thức của class Calculation để tính hiệu của 2 số, nếu kết quả lớn hơn 0 thì sẽ trả về true, ngược lại sẽ là false. Class này sẽ inject bean của đối tượng Calculation sử dụng annotation @Autowire của Spring và được khai báo với annotation @Service như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.huongdanjava.mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.stereotype.Service; @Service public class Application { @Autowired private Calculation calculation; public boolean check(int a, int b) { int result = calculation.sub(a, b); return result > 0; } public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); Application a = ac.getBean(Application.class); if (a.check(2, 4)) { System.out.println("Positive"); } else { System.out.println("Negative"); } } } |
với tập tin cấu hình của Spring nằm trong thư mục src/main/resources với nội dung như sau:
1 2 3 4 5 6 7 8 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.huongdanjava.mockito" /> </beans> |
Kết quả:
Bây giờ, chúng ta sẽ viết Unit Test cho class Application các bạn nhé!
Bởi vì hiện tại class Application không có phương thức Setter cho đối tượng Calculation nên mình sẽ sử dụng annotation @InjectMocks của Mockito để inject đối tượng này vào class Application như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package com.huongdanjava.mockito; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) public class ApplicationTest { @Mock private Calculation calculation; @InjectMocks private Application application; @Test public void testCheck() { Mockito.when(calculation.sub(2, 12)).thenReturn(-10); int a = 2; int b = 12; boolean c = application.check(a, b); assertEquals(false, c); } } |
Như các bạn thấy ở trên, mình đã khai báo sử dụng class Application với annotation @InjectMocks. Việc khai báo này sẽ giúp cho chúng ta có thể inject hết tất cả các đối tượng được khai báo với annotation @Mock trong class ApplicationTest vào đối tượng Application, ở đây là class Calculation.
Nếu bây giờ các bạn chạy Maven test thì sẽ thấy kết quả như sau:
viet
Bạn ơi, upload source code lên giúp mình được ko?
MÌnh ko cấu hình project được.
Đoạn bỏ file vào src/main/resources. Project mình cấu hình ko ra cái package như bạn.
Khanh Nguyen
Trên GitHub đó bạn https://github.com/huongdanjavacom/huongdanjava.com