GP Coder

Trang chia sẻ kiến thức lập trình Java

  • Java Core
    • Basic Java
    • OOP
    • Exception Handling
    • Multi-Thread
    • Java I/O
    • Networking
    • Reflection
    • Collection
    • Java 8
  • Design pattern
    • Creational Pattern
    • Structuaral Pattern
    • Behavior Pattern
  • Web Service
    • SOAP
    • REST
  • JPA
  • Java library
    • Report
    • Json
    • Unit Test
  • Message Queue
    • ActiveMQ
    • RabbitMQ
  • All
Trang chủ Java library Unit Test Một số Annotation cơ bản của JUnit

Một số Annotation cơ bản của JUnit

Đăng vào 05/03/2019 . Được đăng bởi GP Coder . 13213 Lượt xem . Toàn màn hình

Nội dung

  • 1 Một số Annotation cơ bản của JUnit
  • 2 Ví dụ Lifecycle của một Test Class trong JUnit
  • 3 Ví dụ @Ignore a Test
  • 4 Ví dụ Timeout Test
  • 5 Ví dụ Expected Exceptions Test
  • 6 Ví dụ @FixMethodOrder Test

Một số Annotation cơ bản của JUnit

JUnit cung cấp một số Annotation để viết Test như sau:

@Before

Phương thực được đánh dấu với Annotation này sẽ được gọi trước mỗi khi phương thức @Test được gọi.

Nó thường được sử dụng để khởi tạo dữ liệu trước khi thực thi một phương thức @Test.

@After

Phương thực được đánh dấu với Annotation này sẽ được gọi sau mỗi khi phương thức @Test được gọi.

Nó thường được sử dụng để dọn dẹp bộ nhớ sau khi thực thi một phương thức @Test.

@BeforeClass

Phương thực được đánh dấu với Annotation này sẽ được gọi trước khi thực thi tất cả các phương thức @Test được gọi trong một Test class. Phương thức này chỉ được gọi một lần duy nhất.

Phương thức đánh dấu Annotation này phải là static.

Nó thường được sử dụng để khởi tạo dữ liệu cho việc thực thi một Test class.

@AfterClass

Tương tự như @BeforeClass, nhưng nó được gọi sau khi kết thúc thực thi các phương thức @Test. Phương thức này chỉ được gọi một lần duy nhất.

Phương thức đánh dấu Annotation này phải là static.

Nó thường được sử dụng để dọn dẹp bộ nhớ sau khi thực thi tất cả các phương thức @Test trong một Test class.

@Test

Được sử dụng để đánh dấu đây là một phương thức test.@Test(timeout=500)Được sử dụng khi cần giới hạn thời gian thực thi của một phương thức. Nếu vượt quá thời này thì phương thức sẽ fail.

@Test(expected=XxxException.class)

Được sử dụng khi cần test một ngoại lệ được throw ra từ phương thức được test. Nếu ngoại lệ không được throw thì phương thức sẽ fail.

@Ignore

Được sử dụng để đánh dấu phương thức này để được bỏ qua (ignore/ disable), không cần thực thi test.

Nó có thể sử dụng cho một phương thức test hay một class từ một test suite.

@FixMethodOrder

Annotation này cho phép user có thể chọn thứ tự thực thi các phương thức @Test trong một test class.

Một số Annotation khác

Ngoài ra còn một số Annotation khác như: @Rule, @ClassRule, @RunWith, @SuiteClasses, @Parameterized, … chúng ta sẽ cùng tìm hiểu ở một bài viết khác.

Ví dụ Lifecycle của một Test Class trong JUnit

Trong ví dụ bên dưới, chúng ta sẽ thấy được cách mà một Unit test được thi thi với JUnit.


package com.gpcoder.junit;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class JUnitLifeCycleTest {

	@BeforeClass
	public static void runOnceBeforeClass() {
		System.out.println("@BeforeClass - runOnceBeforeClass");
	}

	@AfterClass
	public static void runOnceAfterClass() {
		System.out.println("@AfterClass - runOnceAfterClass");
	}

	@Before
	public void runBeforeTestMethod() {
		System.out.println("@Before - runBeforeTestMethod");
	}

	@After
	public void runAfterTestMethod() {
		System.out.println("@After - runAfterTestMethod");
	}

	@Test
	public void test_method_1() {
		System.out.println("@Test - test_method_1");
	}

	@Test
	public void test_method_2() {
		System.out.println("@Test - test_method_2");
	}
}


Output của chương trình:


@BeforeClass - runOnceBeforeClass
@Before - runBeforeTestMethod
@Test - test_method_1
@After - runAfterTestMethod
@Before - runBeforeTestMethod
@Test - test_method_2
@After - runAfterTestMethod
@AfterClass - runOnceAfterClass

Ví dụ @Ignore a Test

Vì một lý do nào đó, chúng ta muốn tạm thời vô hiệu hóa test case (bỏ qua/ không chạy test case đó).

Thông thường ta sẽ xóa hoặc comment annotation @Test, như thế trình test runner sẽ bỏ qua method đó nhưng đồng thời test case đó cũng sẽ không được report, chúng ta có thể quên mất là có test case đó.

Biện pháp thay thế là sử dụng annotation @Ignore ở trước hoặc sau annotation @Test, sau khi chạy JUnit test, nó vẫn thông báo là có test case đó nhưng đang bị disable. Trong trường hợp muốn ignore tất cả các phương thức của một class test, chỉ đơn giản đặt annotation @Ingore ở mức class.

Ví dụ Ignore method:


package com.gpcoder.junit;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

public class IgnoreTest1 {

	@Test
	@Ignore("This test case will be ignored")
	public void testEquals() {
		String expected = "gpcoder.com";
		Assert.assertEquals(expected, "gpcoder.com");
	}

	@Test
	public void testTrue() {
		Assert.assertTrue(true);
	}

	@Test
	public void testFalse() {
		Assert.assertFalse(false);
	}
}

Output chương trình:

Ví dụ Ignore class:


@Ignore("All test cases of this class will be ignored")
public class IgnoreTest2 {

// Some method test here.
}

Ví dụ Timeout Test

Chúng ta có thể expect thời gian timeout của một test case bằng cách sử dụng thuộc tính timeout trong annoation @Test.

Giả sử chúng ta có một class như sau:


package com.gpcoder.junit.util;

import java.util.concurrent.TimeUnit;

public class TaskUtils {

	public static int doNormalTask() {
		try {
			// Do heavy task
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return 1;
	}

	public static int doHeavyTask() {
		try {
			// Do heavy task
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return 1;
	}
}

Bây giờ chúng ta sẽ viết Unit test với mong muốn thời gian thực thi mỗi phương thức tối đa là 3 giây. Nếu sau thời gian đó, thì xem như phương thức test bị failed. Chúng ta cần cãi tiến performance cho nó.


package com.gpcoder.junit;

import org.junit.Assert;
import org.junit.Test;

import com.gpcoder.junit.util.TaskUtils;

public class TimeoutTest1 {

	@Test(timeout = 3000) // 3 seconds
	public void testTimeout1() {
		int expected = 1;
		int actual = TaskUtils.doNormalTask();
		Assert.assertEquals(expected, actual);
	}

	@Test(timeout = 3000) // 3 seconds
	public void testTimeout2() {
		int expected = 1;
		int actual = TaskUtils.doHeavyTask();
		Assert.assertEquals(expected, actual);
	}
}

Output của chương trình:

Như bạn thấy, tất cả các phương thức test trên đều expected thời gian timeout là 3 giây. Thay vì đặt thuộc tính này trong tất cả các phương thức test, chúng ta có thể sử dụng Timeout rule để áp dụng cho tất cả các phương thức trong class test.


package com.gpcoder.junit;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;

import com.gpcoder.junit.util.TaskUtils;

public class TimeoutTest2 {

	// Set timeout max 3 seconds per each method tested
	@Rule
	public Timeout globalTimeout = Timeout.seconds(3); // 3 seconds

	@Test
	public void testTimeout1() {
		int expected = 1;
		int actual = TaskUtils.doNormalTask();
		Assert.assertEquals(expected, actual);
	}

	@Test
	public void testTimeout2() {
		int expected = 1;
		int actual = TaskUtils.doHeavyTask();
		Assert.assertEquals(expected, actual);
	}
}

Ví dụ Expected Exceptions Test

Giả sử chúng ta có một class cần test như sau:


package com.gpcoder.junit.util;

public class MathUtil {

	private MathUtil() {
		throw new UnsupportedOperationException("Cannot call constructor directly!");
	}

	public static int divide(int dividend, int divisor) {
		if (divisor == 0) {
			throw new IllegalArgumentException("Cannot divide by zero (0).");
		}
		return dividend / divisor;
	}
}

Sử dụng expect exception

Trong một số trường hợp chúng ta cần viết unit test ứng với trường hợp xảy ra exception thì chúng ta expect kết quả là test case đó sẽ xảy ra một Exception chứ không phải một giá trị cụ thể.


package com.gpcoder.junit;

import org.junit.Test;

import com.gpcoder.junit.util.MathUtil;

public class ExceptionTest1 {

	@Test(expected = IllegalArgumentException.class)
	public void testDivideByZero() throws Exception {
		MathUtil.divide(1, 0);
	}
}

Sử dụng try/ catch

Việc sử dụng thuộc tính expected trong annotation @Test có nhược điểm là ta không thể kiểm tra được message của exception hay trạng thái của object sau khi exception được ném ra. Để khắc phục điều đó ta sử dụng try/ catch.


package com.gpcoder.junit;

import org.junit.Assert;
import org.junit.Test;

import com.gpcoder.junit.util.MathUtil;

public class ExceptionTest2 {

	@Test
	public void testDivideByZero() throws Exception {
		try {
			MathUtil.divide(1, 0);
			Assert.fail("Not throw an exception");
		} catch (Exception e) {
			Assert.assertTrue(e instanceof IllegalArgumentException);
			Assert.assertEquals("Cannot divide by zero (0).", e.getMessage());
		}
	}
}

Lưu ý: phương thức fail() nếu được chạy thì tức là test case bị failed. Chúng ta nên sử dụng phương thức này để test exception với try/ catch để đảm bảo rằng phương thức được test phải throw exception hoặc là bị failed.

Sử dụng ExpectedException Rule

Thay vì sử dụng try/ catch exception, chúng ta có thể sử dụng ExpectedException, nó cũng giúp chúng ta test loại và message exception.


package com.gpcoder.junit;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import com.gpcoder.junit.util.MathUtil;

public class ExceptionTest3 {

	@Rule
	public ExpectedException thrown = ExpectedException.none();

	@Test
	public void shouldTestExceptionMessage() throws Exception {
		// Keep this ordering: expect -> call the method which throw an exception
		thrown.expect(IllegalArgumentException.class);
		thrown.expectMessage("Cannot divide by zero (0).");

		MathUtil.divide(1, 0);
	}
}

Ví dụ @FixMethodOrder Test

Các phương thức test trong một class nên được viết một cách độc lập, không phụ thuộc lẫn nhau nên thứ tự thực thi một lớp không quan trọng. Tuy nhiên, chúng ta có thể xác định thứ tự thực thi của các method trong class test bằng cách dùng annotation @FixMethodOrder ở mức class. Có 3 kiểu sắp xếp là:

  • @FixMethodOrder(MethodSorters.DEFAULT): Đây là kiểu sắp xếp mặc định nếu không khai báo @FixMethodOrder, tuy nhiên với kiểu này thì sẽ không thể xác định chính xác method nào sẽ được thực thi trước.
  • @FixMethodOrder(MethodSorters.JVM): Thứ tự các method test dựa theo JVM. Tuy nhiên thứ tự này có thể bị thay đổi khi thực thi.
  • @FixMethodOrder(MethodSorters.NAME_ASCENDING): Thứ tự các method được thực thi dựa theo tên method. Thông thường, nếu cần sắp xếp thì kiểu này được chọn bởi nó giữ đúng thứ tự theo tên phương thức, không bị thay đổi như 2 kiểu trên.

Ví dụ:


package com.gpcoder.junit;

import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class FixMethodOrderTest {

	@Test
	public void test_11() {
		Assert.assertTrue(true);
	}

	@Test
	public void test_1() {
		Assert.assertTrue(true);
	}

	@Test
	public void test_10() {
		Assert.assertTrue(true);
	}

	@Test
	public void test_2() {
		Assert.assertTrue(true);
	}
}

Output của chương trình:

Trên đây là một số Annotation cơ bản và thường được sử dụng trong JUnit test. Có một số phương thức có thể gây khó hiểu cho các bạn như Assert.assertTrue(), Assert.assertFalse(), … Đây là các API của JUnit để hỗ trợ kiểm tra kết quả mong muốn. Chúng ta sẽ cùng tìm hiểu về các API này trong bài viết tiếp theo.

5.0
04
Nếu bạn thấy hay thì hãy chia sẻ bài viết cho mọi người nhé! Và Donate tác giả

Shares

Chuyên mục: Unit Test Được gắn thẻ: JUnit

Giới thiệu JUnit
Một số API của JUnit – Assert, Assume, Test Runner

Có thể bạn muốn xem:

  • Unit Testing trong phát triển phần mềm hiện đại (03/03/2019)
  • PowerMockito – Suppressing Unwanted Behavior (10/04/2019)
  • JUnit – Parameterized Test (08/03/2019)
  • Tổng hợp các bài viết về Unit Test trong Java (15/04/2019)
  • Làm thế nào để Test Jersey Rest API với JUnit? (22/08/2019)

Bình luận

bình luận

Tìm kiếm

Bài viết mới

  • Clean code 13/01/2024
  • Giới thiệu CloudAMQP – Một RabbitMQ server trên Cloud 02/10/2020
  • Kết nối RabbitMQ sử dụng Web STOMP Plugin 19/06/2020
  • Sử dụng publisher confirm trong RabbitMQ 16/06/2020
  • Sử dụng Dead Letter Exchange trong RabbitMQ 13/06/2020

Xem nhiều

  • Hướng dẫn Java Design Pattern – Factory Method (97945 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (97606 lượt xem)
  • Giới thiệu Design Patterns (87603 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (86260 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (83700 lượt xem)

Nội dung bài viết

  • 1 Một số Annotation cơ bản của JUnit
  • 2 Ví dụ Lifecycle của một Test Class trong JUnit
  • 3 Ví dụ @Ignore a Test
  • 4 Ví dụ Timeout Test
  • 5 Ví dụ Expected Exceptions Test
  • 6 Ví dụ @FixMethodOrder Test

Lưu trữ

Thẻ đánh dấu

Annotation Authentication Basic Java Behavior Pattern Collection Creational Design Pattern Cấu trúc điều khiển Database Dependency Injection Design pattern Eclipse Exception Executor Service Google Guice Gson Hibernate How to Interceptor IO Jackson Java 8 Java Core JDBC JDK Jersey JMS JPA json JUnit JWT Message Queue Mockito Multithreading OOP PowerMockito RabbitMQ Reflection Report REST SOAP Structuaral Pattern Swagger Thread Pool Unit Test Webservice

Liên kết

  • Clean Code
  • JavaTpoint
  • Refactoring Guru
  • Source Making
  • TutorialsPoint
  • W3Schools Online Web Tutorials

Giới thiệu

GP Coder là trang web cá nhân, được thành lập với mục đích lưu trữ, chia sẽ kiến thức đã học và làm việc của tôi. Các bài viết trên trang này chủ yếu về ngôn ngữ Java và các công nghệ có liên quan đến Java như: Spring, JSF, Web Services, Unit Test, Hibernate, SQL, ...
Hi vọng góp được chút ít công sức cho sự phát triển cộng đồng Coder Việt.

Donate tác giả

Tìm kiếm các bài viết của GP Coder với Google Search

Liên hệ

Các bạn có thể liên hệ với tôi thông qua:
  • Trang liên hệ
  • Linkedin: gpcoder
  • Email: contact@gpcoder.com
  • Skype: ptgiang56it

Follow me

Copyright 2025 © GP Coder · All Rights Reserved · Giới thiệu · Chính sách · Điều khoản · Liên hệ ·

Share

Blogger
Delicious
Digg
Email
Facebook
Facebook messenger
Flipboard
Google
Hacker News
Line
LinkedIn
Mastodon
Mix
Odnoklassniki
PDF
Pinterest
Pocket
Print
Reddit
Renren
Short link
SMS
Skype
Telegram
Tumblr
Twitter
VKontakte
wechat
Weibo
WhatsApp
X
Xing
Yahoo! Mail

Copy short link

Copy link