In the last article, we’ve already talk about Test Double in general. In this article, we will talk about on of test double, called stub.

Testing a component can be helped with another collaborator component with predefined behavior. This is called stubbing.

💡  Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test. – Martin Fowler

Using stub in Diagram

Let’s create a Stub.

Creating a Stub

Let say we have a component, a use case, LoadTransactionsFromRemoteUseCase. This use case will have a success case, and failure case as a return completion value.

protocol LoadTransactionsUseCase {
	func execute(completion: @escaping (Result<[Transaction], Error>) -> Void)

And we have an implementation for that use case, named LoadTransactionsFromRemoteUseCase

class LoadTransactionsFromLocalUseCase: LoadTransactionsUseCase {
	private let store: TransactionCacheStore
	init(store: TransactionCacheStore) { = store
	func execute(completion: @escaping (Result<[Transaction], Error>) -> Void) {
		store.loadTransactions { result in
			switch result {
				case .success(let transactions):
				case .failure(let error):

We can create the non real with predefined store with the stub, using the same interface of TransactionCacheStore.

So, from the client point of view, we want to create with both success and fail store like this :

func test_execute_returnNonEmptyTransactions() {
  let nonEmptyItems = createNonEmptyItems()
  let storeStub = TransactionStoreStub(result: .success(nonEmptyItems))
  let sut = LoadTransactionsFromLocalUseCase(store: storeStub)
  // do something for testing ...

In the code above, we create our test instance, the LoadTransactionsFromLocalUseCase with the predefined behavior using the stub and inject it on the constructor. so, when we call the sut.execute() , we should get the success case with non empty items behavior.

Let’s implement the stub

class TransactionCacheStoreStub: TransactionCacheStore {
  private let result: Result<[Transaction], Error>
  init(result: Result) { 
    self.result = result

  func loadTransactions(completion: (Result<[Transaction], Error>) -> Void) {

This implementation is a stub has behavior as following :

  • the success or failure behavior can both be injected
  • Using constructor or intializer injection, since it is the most preferred way

To elaborate more, this implementation is a stub, meaning, it has predefined behavior for unit testing purpose. The behavior can be both success and failure scenarios. If success, returns array of transaction. If failure, return any Error type.

This stub test double helps our test for LoadTransactionsFromLocalUseCase component, since it can returning a success case with empty item, with items, and with certain error without communicating to a real backend. Therefore, we can verify later that our system under test, or SUT, is able to returning all of those 3 cases correctly.


Stub is one of test double, that can helps you to test a component’s behavior, the SUT, without having a real or production implementation of its collaborator. This test double component provides a predefined value configured so that the SUT component will responds based on the Stub values. Stub only defines asnwer or return , not capturing values nor others.

Reference :

Dependency Injection Principles, Practices, and Patterns by Steven van Deursen & Mark Seemann

Test Double (Martin Fowler)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s