Test with Testify and Mockery in Go
Tags: go, test, backend, testing
Published: 2023-01-16 04:23:12

---
title: Test with Testify and Mockery in Go
published: true
description: In this blog, we will learn about writing the unit test with Testify and Mockery in Go (Golang) project.
tags: go, golang, test, backend, testing
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/doinxs9ze6tm0g7a9g7b.png
canonical_url: https://amitshekhar.me/blog/test-with-testify-and-mockery-in-go
---

I am [**Amit Shekhar**](https://amitshekhar.me), a mentor helping developers in getting high-paying tech jobs.

In this blog, we will learn about writing the unit test with Testify and Mockery in Go (Golang) project.

**This article was originally published at [amitshekhar.me](https://amitshekhar.me/blog/test-with-testify-and-mockery-in-go).**

These two packages are very useful during the testing of any Go files.

- **testify**: A toolkit with common assertions and mocks that plays nicely with the standard library.
- **mockery**: A mock code autogenerator for Golang used in testing.

As we know that the testify package is used for the purpose of the assertions.

mockery package provides the ability to easily generate mocks for Golang interfaces using the testify package. It removes the boilerplate coding required to use mocks.

So, let's start learning to use both packages to write tests in Go.

I will be using the below-mentioned project for the implementation part. The project follows a clean architecture in Go Language. You can find the complete code for unit testing using the Testify and Mockery mentioned in the blog in the project itself.

Link to the project: [Go Backend Clean Architecture](https://github.com/amitshekhariitbhu/go-backend-clean-architecture).

In the project, we have Controller, Usecase, and Repository. In this blog, we will learn to write the test by taking the Usecase as an example.

Consider the `TaskUsecase` present inside the given project.

```go
package usecase

import (
	"context"
	"time"

	"github.com/amitshekhariitbhu/go-backend-clean-architecture/domain"
)

type taskUsecase struct {
	taskRepository domain.TaskRepository
	contextTimeout time.Duration
}

func NewTaskUsecase(taskRepository domain.TaskRepository, timeout time.Duration) domain.TaskUsecase {
	return &taskUsecase{
		taskRepository: taskRepository,
		contextTimeout: timeout,
	}
}

func (tu *taskUsecase) Create(c context.Context, task *domain.Task) error {
	ctx, cancel := context.WithTimeout(c, tu.contextTimeout)
	defer cancel()
	return tu.taskRepository.Create(ctx, task)
}

func (tu *taskUsecase) FetchByUserID(c context.Context, userID string) ([]domain.Task, error) {
	ctx, cancel := context.WithTimeout(c, tu.contextTimeout)
	defer cancel()
	return tu.taskRepository.FetchByUserID(ctx, userID)
}
```

So, our aim is to test the Usecase that is dependent on Repository. We will have to mock the Repository.

As the mockery generates the mocks for Golang interfaces, suppose we have the following interface for the `TaskRepository`.

```go
type TaskRepository interface {
	Create(c context.Context, task *Task) error
	FetchByUserID(c context.Context, userID string) ([]Task, error)
}
```

As a next step, we need to run the following command to generate the mock for this repository.

```bash
mockery --dir=domain --output=domain/mocks --outpkg=mocks --all
```

Note: You will have to modify the command based on your project structure and directory.

It should generate the `TaskRepository` mock that we will be using for the testing.

Now, that mock for the Repository is also ready, we can write the test for the Usecase.

We will write the test for the `FetchByUserID` method present in the Usecase.

Here, we are testing two cases:

- Success: The repository returns data successfully without any errors.
- Error: The repository returns an error.

The following is the code showing how to write those tests using the testify and mockery:

```go
package usecase_test

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/amitshekhariitbhu/go-backend-clean-architecture/domain"
	"github.com/amitshekhariitbhu/go-backend-clean-architecture/domain/mocks"
	"github.com/amitshekhariitbhu/go-backend-clean-architecture/usecase"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

func TestFetchByUserID(t *testing.T) {
	mockTaskRepository := new(mocks.TaskRepository)
	userObjectID := primitive.NewObjectID()
	userID := userObjectID.Hex()

	t.Run("success", func(t *testing.T) {

		mockTask := domain.Task{
			ID:     primitive.NewObjectID(),
			Title:  "Test Title",
			UserID: userObjectID,
		}

		mockListTask := make([]domain.Task, 0)
		mockListTask = append(mockListTask, mockTask)

		mockTaskRepository.On("FetchByUserID", mock.Anything, userID).Return(mockListTask, nil).Once()

		u := usecase.NewTaskUsecase(mockTaskRepository, time.Second*2)

		list, err := u.FetchByUserID(context.Background(), userID)

		assert.NoError(t, err)
		assert.NotNil(t, list)
		assert.Len(t, list, len(mockListTask))

		mockTaskRepository.AssertExpectations(t)
	})

	t.Run("error", func(t *testing.T) {
		mockTaskRepository.On("FetchByUserID", mock.Anything, userID).Return(nil, errors.New("Unexpected")).Once()

		u := usecase.NewTaskUsecase(mockTaskRepository, time.Second*2)

		list, err := u.FetchByUserID(context.Background(), userID)

		assert.Error(t, err)
		assert.Nil(t, list)

		mockTaskRepository.AssertExpectations(t)
	})

}
```

**Case 1: Success**

In this case, we have mocked the method of Repository to return success with the data.

Then, we are passing the mocked Repository into the Usecase.

After that, we are calling the method of the Usecase.

And then finally, asserting to check whether everything is as expected or not.

**Case 2: Error**

In this case, we have mocked the method of Repository to return an error.

Then, we are passing the mocked Repository into the Usecase.

After that, we are calling the method of the Usecase.

And then finally, asserting to check whether everything is as expected or not.

Now, our test is ready to be run. We can run the test and check.

We can run all the tests with the following command:

```go
go test ./...
```

This is how we can write the unit test by using the Testify and Mockery package in Go (Golang) project.

I will highly recommend going through the project and checking the tests written for the Controller, Usecase, and Repository.

Link to the project: [Go Backend Clean Architecture](https://github.com/amitshekhariitbhu/go-backend-clean-architecture).

That's it for now.

Thanks

[**Amit Shekhar**](https://amitshekhar.me)

You can connect with me on:

- [Twitter](https://twitter.com/amitiitbhu)
- [YouTube](https://www.youtube.com/@amitshekhar)
- [LinkedIn](https://www.linkedin.com/in/amit-shekhar-iitbhu)
- [GitHub](https://github.com/amitshekhariitbhu)

[**Read all of my high-quality blogs here.**](https://amitshekhar.me/blog)