Developing a RESTful API with Go, Gin, and GORM — Part 2 (Repository Setup, Table Driven Testing)

Venu Prasanna M
4 min readSep 14, 2022

--

In this article, we will continue adding the repository methods for our handler to consume and also explore writing table-driven tests. Before going through this article please read Part 1 for the initial project setup.

Project Structure

Movie. go

In this file, we will add the movie struct to hold the movie data while we fetch it from the database using the repository methods. For now, all we need is just the Movie name, Id, CreateAt, UpdateAt.

In model/movie.go

Why Repository pattern?

This pattern is used to decouple the business logic and the data access layers in the application.

Repository. go

Now let’s set up the repository, this file will have the repository methods that will fetch the movie records from the database. As we are going to implement pagination we will be fetching the data with offset and also count the total number of movie records available in the database.

First, let’s define the interface of our Repository with the FindAll method which will provide page and limit, and in return, we expect a list of movies or error.

Now let’s define a repository struct and a factory method to create this repository to which we will be attaching the database.

Now the only step that is left out is to implement the FindAll method that we have defined in the repository interface. Let’s do that after the test setup.

Movie_test. go

In this file, we will be adding the repository test cases to test the FindAll method. To test this repository method, we will need a database running to test against, so to this, we will be running a Postgres database image using a test container.

Test Container

It provides a lightweight, throwaway instance of any application that can run on a Docker container.

let’s install test container-go and Postgres driver using the following command

$ go get github.com/testcontainers/testcontainers-go
$ go get gorm.io/driver/postgres

In tests/repository/movie_test.go . Add the TestMain method which will be the first method to get invoked before running any test. In this method, we will be doing the following.

  • Configuring & Starting the Test Container with Postgres database image.
  • Migrating movie model to test database
  • then running all the tests and terminating the test container

Now let’s write the test cases for the FindAll repository method with the TDD approach. Table-driven Tests will avoid duplication of tests. For each test case, only the input and expected output and name will change, everything else is a boilerplate code.

First, let’s create an args struct with limit and page fields which will be the input struct for each test case. Now we need one more struct with fields args, name, expected Total, and expected the record to hold the different test cases.

we are going to perform the test for +ve flow with the following cases.

  1. should return 1 record for input limit 1 and page 1.
  2. should return 5 records in 1 page for input limit 5 and page 1.
  3. should return the next 5 records on page 2 for input limit 5 and page 2.
  4. should return all records on page 1 for input limit 10 and page 1.

If we try to test now it will fail as we have not yet implemented the FindAll method. so let’s quickly implement that method. Our method should return the movie list in descending order based on CreateAt stamp, total movie records present in the database, and error.

Pagination

If we try to fetch really large data in a single request then it will take a long time and scrolling on a single page will also get very long. so to avoid this we have to break the data into smaller parts called pages.

Calculating offset for pagination

page = 1, limit = 5, offset = (page-1) * limit = (1–1) * 5= 0

page = 2, limit = 5, offset = (page-1) * limit = (2–1) * 5= 5

page = 3, limit = 5, offset = (page-1) * limit = (3–1) * 5= 10

this way we will skip the first few records using the offset. If the page = 1, and limit = 5 the offset is 0 meaning return the first 5 records without skipping any. In the case of page = 2 and limit = 5 the offset is 5 where we skip the first 5 records and fetch the next 5 for page 2.

In movie/repository.go.

After updating this method if you run the test should pass. We are left with consuming this repository method in a handler and exposing the handler using an API.

Coming up next

  • Pagination using GIN + GORM

--

--