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 Mockito – Verifying Behavior

Mockito – Verifying Behavior

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

Nội dung

  • 1 Giới thiệu
  • 2 Một số ví dụ Verifying Behavior

Giới thiệu

Khi viết Unit Test, chúng ta cần thực hiện một số Assert để xác nhận expected result và actual result là như nhau. Đối với các mock object, chúng ta cũng cần verify một vài behavior đã được gọi hay chưa.

Trong Mockito, chúng ta có thể thực hiện verify các mock object thông qua phương thức Mockito.verfify():


verify(mockedObject, times(2)).someMethodOfMockObject(argurments);

Một số ví dụ Verifying Behavior

Thông thường, viết Unit Test sử dụng Mockito bao gồm các bước cơ bản sau:

  • Tạo mock object.
  • Điều khiển một mock object và xác định phải làm gì khi các phương thức cụ thể của mock object được gọi.
  • Gọi phương thức.
  • Verify phương thức đã được gọi hay chưa.

Ví dụ:


// 1: Create mock object
List mock = mock(List.class);
// 2: Stub - Control mock’s behavior 
when(mock.add("gpcoder")).thenReturn(true);
// 3: Call behavior
mock.add("gpcoder");
// 4: Verify behavior
verify(mock).add("gpcoder");

Verify số lần phương thức được gọi

Một số phương thức được sử dụng để verify số lần gọi:

  • times(number) : verify chính xác số lần phương thức được gọi.
  • never() : verify phương thức không bao giờ được gọi.
  • atLeastOnce() : verify phương thức được gọi ít nhất 1 lần.
  • atLeast(number) : verify phương thức được gọi ít nhất number lần.
  • atMost(number) : verify phương thức được gọi nhiều nhất number lần.
  • verifyNoMoreInteractions(mockedObjects) : xác nhận rằng không có bất kỳ một phương thức nào của mockedObject được gọi mà không được gọi verfify() để kiểm tra.
  • verifyZeroInteractions() :tương tự như verifyNoMoreInteractions().

package com.gpcoder.mockito.verify;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

public class VerifyTest {

	private List<String> mockedList;

	@Before
	public void prepareForTest() {
		// Mock creation
		mockedList = Mockito.mock(List.class);
	}

	@Test
	public void zeroTimeTest() {
		// Verifies certain behavior never happened
		Mockito.verify(mockedList, Mockito.never()).add("gpcoder.com");
		Mockito.verify(mockedList, Mockito.times(0)).add("gpcoder.com");
	}

	@Test
	public void oneTimeTest() {
		// Using mock object
		mockedList.add("gpcoder.com");

		// Verifies certain behavior happened once
		Mockito.verify(mockedList).add("gpcoder.com"); // Default one time
		Mockito.verify(mockedList, Mockito.times(1)).add("gpcoder.com");
	}

	@Test
	public void atLeastTest() {
		// Using mock object
		mockedList.add("one");
		mockedList.add("two");
		mockedList.add("three");

		// Verifies certain behavior happened at least once
		Mockito.verify(mockedList, Mockito.atLeastOnce()).add(Mockito.anyString());

		// Verifies certain behavior happened at least twice
		Mockito.verify(mockedList, Mockito.atLeast(2)).add(Mockito.anyString());
	}

	@Test
	public void atMostTest() {
		// Using mock object
		mockedList.add("one");
		mockedList.add("two");

		// Verifies certain behavior happened at most twice
		Mockito.verify(mockedList, Mockito.atMost(2)).add(Mockito.anyString());
	}

	@Test
	public void verifyNoMoreInteractionsTest() {
		// Create mock object
		List<String> mockOne = Mockito.mock(List.class);

		// Using mocks - only mockOne is interacted
		mockOne.add("one");

		// Uncomment this code will make the test case failed because it is unverified interaction
		// mockOne.get(0);

		// Ordinary verification
		Mockito.verify(mockOne).add("one");

		// Checks if any of given mocks has any unverified interaction. You can use this
		// method after you verified your mocks - to make sure that nothingelse was
		// invoked on your mocks.
		Mockito.verifyNoMoreInteractions(mockOne);
	}

	@Test
	public void verifyZeroInteractionsTest() {
		// Create mock object
		List<String> mockOne = Mockito.mock(List.class);
		List<String> mockTwo = Mockito.mock(List.class);
		List<String> mockThree = Mockito.mock(List.class);

		// Using mocks - only mockOne is interacted
		mockOne.add("one");

		// Ordinary verification
		Mockito.verify(mockOne).add("one");

		// Verify that method was never called on a mock
		Mockito.verify(mockOne, Mockito.never()).add("two");

		// Verifies that no interactions happened on given mocks beyond the previously
		// verified interactions
		Mockito.verifyZeroInteractions(mockTwo, mockThree);
	}

	@Test
	public void clearInvocationsTest() {
		// Create mock object
		List<String> mockOne = Mockito.mock(List.class);
		List<String> mockTwo = Mockito.mock(List.class);

		// Using mocks - only mockOne is interacted
		mockOne.add("one");
		mockTwo.add("one");

		// Use this method in order to only clear invocations, when stubbing is non-trivial.
		Mockito.clearInvocations(mockOne, mockTwo);
		// Another way: reset() a mock so that it can be reused later
		// Mockito.reset(mockOne, mockTwo);

		// Verifies that no interactions happened on given mocks beyond the previously
		// verified interactions
		Mockito.verifyZeroInteractions(mockOne, mockTwo);
	}
}

Verify các tham số (argument) của phương thức

Đối với các void method, thông thường chúng ta có thể verify các thông tin:

  • Số lần phương thức được gọi.
  • Giá trị các tham số.

Để verify các tham số (argument) của các phương thức, chúng ta có thể sử dụng Argument Matcher hoặc Argument Captor.


package com.gpcoder.mockito.verify;

import static org.hamcrest.Matchers.hasItem;

import java.util.Arrays;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

public class ArgumentMatcherTest {

	@Captor
	private ArgumentCaptor<List<String>> captor;

	@Mock
	private List<String> mockedList;

	@Before
	public void prepareForTest() {
		MockitoAnnotations.initMocks(this);
	}

	@Test
	public final void argumentCaptorTest() {
		List<String> asList = Arrays.asList("gpcoder.com", "mockito", "junit");

		mockedList.addAll(asList);

		// Verify value on arguments
		Mockito.verify(mockedList).addAll(captor.capture());
		final List<String> capturedArgument = captor.getValue();
		Assert.assertEquals(3, capturedArgument.size());
		Assert.assertThat(capturedArgument, hasItem("gpcoder.com"));
	}

	@Test
	public void argumentMatcherTest() {
		List<String> asList = Arrays.asList("gpcoder.com", "mockito", "junit");

		mockedList.addAll(asList);

		// Verifies certain behavior happened at at least once with the given value is
		// "gpcoder.com"
		Mockito.verify(mockedList).addAll(Mockito.anyCollection());
		Mockito.verify(mockedList, Mockito.atLeast(1))
				.addAll(Mockito.argThat(collection -> collection.contains("gpcoder.com")));
	}
}

Verify thứ tự phương thức được gọi

Trong một số trường hợp, chúng ta cần verify thứ tự thực thi các phương thức. Chẳng hạn, chức năng tạo user bao gồm các bước sau:

  • Tạo mã user.
  • Lưu thông tin user vào cơ sở dữ liệu.
  • Gửi mail xác nhận.
  • Hiển thị thông báo kết quả thêm thành công/ thất bại.

Trong Mockito, để verify thứ tự các phương thức được gọi chúng ta có thể sử dụng các phương thức hỗ trợ của class InOrder. Để tạo InOrder, chúng ta sử dụng phương thức Mockito.inOrder(mockedObjects).

UserCreationTemplate.java


package com.gpcoder.mockito.verify;

public abstract class UserCreationTemplate {

	public void createUser() {
		createUserCode();

		saveUser();

		sendEmail();

		showResult();
	}

	protected abstract String createUserCode();

	protected abstract void saveUser();

	protected abstract void sendEmail();

	protected abstract void showResult();

}

InOrderTest.java


package com.gpcoder.mockito.verify;

import java.util.List;

import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;

public class InOrderTest {

	@Test
	public void singleMockTest() {
		// Create mock object
		List<String> mockedList = Mockito.mock(List.class);

		// Using mock object
		mockedList.add("was added first");
		mockedList.add("was added second");

		// Create an inOrder verifier for a single mock
		InOrder inOrder = Mockito.inOrder(mockedList);

		// Following will make sure that add is first called with "was added first",
		// then with "was added second"
		inOrder.verify(mockedList).add("was added first");
		inOrder.verify(mockedList).add("was added second");
	}

	@Test
	public void multipleMocksTest() {
		// Create mock object
		List<String> mockedList1 = Mockito.mock(List.class);
		List<String> mockedList2 = Mockito.mock(List.class);

		// Using mock object
		mockedList1.add("was added first for 1st list");
		mockedList2.add("was added first for 2nd list");
		mockedList1.add("was added second for 1st list");

		// Create inOrder object passing any mocks that need to be verified in order
		InOrder inOrder = Mockito.inOrder(mockedList1, mockedList2);

		// Following will make sure that firstMock was called before secondMock
		inOrder.verify(mockedList1).add(Mockito.anyString());
		inOrder.verify(mockedList2).add(Mockito.anyString());
		inOrder.verify(mockedList1).add(Mockito.anyString());
	}

	@Test
	public void verifyOrderingExecutionTest() {
		// Create mock object
		UserCreationTemplate mockedObject = Mockito.spy(UserCreationTemplate.class);

		// Using mock object
		mockedObject.createUser();

		// Create inOrder object passing any mocks that need to be verified in order
		InOrder inOrder = Mockito.inOrder(mockedObject);

		// Verify ordering execution
		inOrder.verify(mockedObject).createUserCode();
		inOrder.verify(mockedObject).saveUser();
		inOrder.verify(mockedObject).sendEmail();
		inOrder.verify(mockedObject).showResult();
	}
}

Verify thời gian thực thi (timeout)

Trong mockito, chúng ta cũng có thể verify thời gian thực thi của các phươn thức chạy async thông qua 2 phương thức:

  • timeout(miliseconds) : verify phương thức được được gọi trong một khoảng thời gian miliseconds được chỉ định.
  • after(miliseconds) : tương tự như timeout. Tuy nhiên, timeout() sẽ thoát ngay lập tức khi một phương thức đã được verify, còn after() sẽ chờ cho đến khi hết thời gian được chỉ định mới thực hiện verify.

CustomList.java


package com.gpcoder.mockito.verify;

import java.util.List;
import java.util.concurrent.TimeUnit;

public class CustomList {

	public static final int TIME_TO_EXECUTE_IN_MILISECONDS = 50;

	private List<String> list;

	public List<String> getList() {
		return list;
	}

	public boolean add(String item) {
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					TimeUnit.MILLISECONDS.sleep(TIME_TO_EXECUTE_IN_MILISECONDS);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				getList().add(item);
			}
		});
		t.start();
		return true;
	}
}

TimeoutTest.java


package com.gpcoder.mockito.verify;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

public class TimeoutTest {

	@InjectMocks
	private CustomList mockedList;

	@Mock
	private List<String> list;

	@Before
	public void prepareForTest() {
		// Mock creation
		MockitoAnnotations.initMocks(this);
	}

	/**
	 * Verification will be triggered after given amount of millis, allowing testing
	 * of async code.
	 * 
	 * timeout() exits immediately with success when verification passes
	 */
	@Test
	public void timeoutTest() {
		// Using mock object
		mockedList.add("gpcoder.com");

		// Verify call to add method to be called once times within 100 ms
		Mockito.verify(list, Mockito.timeout(100)).add("gpcoder.com"); // Default once times
		Mockito.verify(list, Mockito.timeout(100).times(1)).add("gpcoder.com");
	}

	/**
	 * Verification will be triggered after given amount of millis, allowing testing
	 * of async code.
	 * 
	 * after() awaits full duration to check if verification passes
	 */
	@Test
	public void afterTest() {
		// Using mock object
		mockedList.add("gpcoder.com");

		// Verify call to add method to be called once times within 100 ms
		Mockito.verify(list, Mockito.after(100)).add("gpcoder.com"); // Default once times
		Mockito.verify(list, Mockito.after(100).times(1)).add("gpcoder.com");
	}
}

Thử thay đổi giá trị TIME_TO_EXECUTE_IN_MILISECONDS là 50, 100, 150 và chạy thử để xem các kết quả khác nhau.

Tài liệu tham khảo:

  • https://static.javadoc.io/org.mockito/mockito-core/2.24.5/org/mockito/Mockito.html
5.0
07
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, Mockito

Mockito – Control mock’s behavior
Giới thiệu Powermock

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

  • Làm thế nào để thực thi một nhóm các class test trong JUnit? (07/03/2019)
  • Làm sao test một Abstract Class trong Java? (12/04/2019)
  • Một số API của JUnit – Assert, Assume, Test Runner (06/03/2019)
  • JUnit – HTML Report với Surefire maven plugin (25/03/2019)
  • Tìm hiểu về kiểm thử (Tesing) trong phát triển phần mềm (27/02/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 (97940 lượt xem)
  • Hướng dẫn Java Design Pattern – Singleton (97603 lượt xem)
  • Giới thiệu Design Patterns (87600 lượt xem)
  • Lập trình đa luồng trong Java (Java Multi-threading) (86257 lượt xem)
  • Giới thiệu về Stream API trong Java 8 (83695 lượt xem)

Nội dung bài viết

  • 1 Giới thiệu
  • 2 Một số ví dụ Verifying Behavior

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