Skip to content

Commit

Permalink
feat: use gomock for unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
AlanJhu committed Dec 26, 2023
1 parent e667fd2 commit 30bf490
Show file tree
Hide file tree
Showing 20 changed files with 529 additions and 36 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ test:
server:
go run main.go

.PHONY: postgres createdb dropdb migrateup migratedown sqlc server
mock:
mockgen -package mockdb -destination db/mock/store.go github.com/Malarkey-Jhu/simple-bank/db/sqlc Store

.PHONY: postgres createdb dropdb migrateup migratedown sqlc server mock
130 changes: 130 additions & 0 deletions api/account_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package api

import (
"bytes"
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

mockdb "github.com/Malarkey-Jhu/simple-bank/db/mock"
db "github.com/Malarkey-Jhu/simple-bank/db/sqlc"
"github.com/Malarkey-Jhu/simple-bank/util"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)

func TestAccountApi(t *testing.T) {
account := randomAccount()

testCases := []struct {
name string
accountID int64
buildStubs func(store *mockdb.MockStore)
checkResponse func(t *testing.T, recorder *httptest.ResponseRecorder)
}{
{
name: "OK",
accountID: account.ID,
buildStubs: func(store *mockdb.MockStore) {
// build stubs
store.EXPECT().GetAccount(gomock.Any(), account.ID).Times(1).Return(account, nil)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
// check status code
require.Equal(t, http.StatusOK, recorder.Code)
// check body
requireBodyMatchAccount(t, recorder.Body, account)
},
},
{
name: "Account Not Found",
accountID: account.ID,
buildStubs: func(store *mockdb.MockStore) {
// build stubs
store.EXPECT().GetAccount(gomock.Any(), account.ID).Times(1).Return(db.Account{}, sql.ErrNoRows)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
// check status code
require.Equal(t, http.StatusNotFound, recorder.Code)
},
},
{
name: "Internal Error",
accountID: account.ID,
buildStubs: func(store *mockdb.MockStore) {
// build stubs
store.EXPECT().GetAccount(gomock.Any(), account.ID).Times(1).Return(db.Account{}, sql.ErrConnDone)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
// check status code
require.Equal(t, http.StatusInternalServerError, recorder.Code)
},
},
{
name: "Invalid Request",
accountID: 0,
buildStubs: func(store *mockdb.MockStore) {
// build stubs
store.EXPECT().GetAccount(gomock.Any(), account.ID).Times(0)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
// check status code
require.Equal(t, http.StatusBadRequest, recorder.Code)
},
},
}

for i := range testCases {
tc := testCases[i]

t.Run(tc.name, func(t *testing.T) {

ctrl := gomock.NewController(t)
defer ctrl.Finish()

store := mockdb.NewMockStore(ctrl)

tc.buildStubs(store)

// start test server and send requests
server := NewServer(store)

recorder := httptest.NewRecorder()

url := fmt.Sprintf("/accounts/%d", tc.accountID)

request, err := http.NewRequest(http.MethodGet, url, nil)
require.NoError(t, err)

// send request and record the response in the recoder
server.router.ServeHTTP(recorder, request)
tc.checkResponse(t, recorder)
})
}

}

func randomAccount() db.Account {
return db.Account{
ID: util.RandomInt(1, 1000),
Owner: util.RandomOwner(),
Balance: util.RandomMoney(),
Currency: util.RandomCurrency(),
}
}

func requireBodyMatchAccount(t *testing.T, body *bytes.Buffer, account db.Account) {
data, err := ioutil.ReadAll(body)
require.NoError(t, err)

var responseAccount db.Account

err = json.Unmarshal(data, &responseAccount)
require.NoError(t, err)
require.Equal(t, responseAccount, account)

}
14 changes: 14 additions & 0 deletions api/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package api

import (
"os"
"testing"

"github.com/gin-gonic/gin"
)

func TestMain(m *testing.M) {
gin.SetMode(gin.TestMode)

os.Exit(m.Run())
}
4 changes: 2 additions & 2 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
)

type Server struct {
store *db.Store
store db.Store
router *gin.Engine
}

// NewServer creates a Http server and setup routing
func NewServer(store *db.Store) *Server {
func NewServer(store db.Store) *Server {
server := &Server{store: store}

router := gin.Default()
Expand Down
Loading

0 comments on commit 30bf490

Please sign in to comment.