Help us understand the problem. What is going on with this article?

testify/suitとモックを用いてgolangのユニットテストを作成する

概要

Golangのユニットテストをtestify/suitを用いて書きました。
https://github.com/stretchr/testify/tree/master/suite
Golangのテスト時のモックに関しても一緒に書きたいと思います。

実装

実際のテストの中身は今回の記事の対象外の為、一番簡易なMVCで言う所のController層のテストで紹介します。

controller.go
package controller

import (
    "article/api/service"
    "net/http"

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

type Controller struct {
    service service.ServiceInterface
}

func NewController(service service.ServiceInterface) *Controller {
    return &Controller{service: service}
}

type ControllerInterface interface {
    GetArticleController(c *gin.Context)
}

func (controller Controller) GetArticleController(c *gin.Context) {
    articles := controller.service.GetArticleService()
    c.JSON(http.StatusOK, articles)
}

controller.goから参照されており、テストではモックにするservice.goは以下になります。

service.go
package service

import (
    "fmt"

    "github.com/gin-gonic/gin"

    "article/api/dao"
    "article/api/util"
)

type Service struct {
    dao dao.DaoInterface
}

func NewService(dao dao.DaoInterface) *Service {
    return &Service{dao: dao}
}

type ServiceInterface interface {
    GetArticleService() []util.Article
}

func (s Service) GetArticleService() []util.Article {
    //some code
}

実際のcontroller.goのテストファイルは以下のようになります。

controller_test.go
package controller

import (
    "article/api/service"
    "article/api/util"
    "net/http/httptest"
    "testing"

    "github.com/gin-gonic/gin"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/suite"
)

type MockServiceInterface struct {
}

func (_m *MockServiceInterface) GetArticleService() []util.Article {
    return nil
}

type ControllerSuite struct {
    suite.Suite
    controller *Controller
    service    service.ServiceInterface
}

func (s *ControllerSuite) SetupTest() {
    s.controller = NewController(s.service)
    s.controller.service = &MockServiceInterface{}
}

func TestControllerSuite(t *testing.T) {
    suite.Run(t, new(ControllerSuite))
}

func (s *ControllerSuite) TestGetArticleController() {
    c, _ := gin.CreateTestContext(httptest.NewRecorder())
    s.controller.GetArticleController(c)
    assert.Equal(s.T(), 200, c.Writer.Status())
}
  • MockServiceInterfaceに上書きすることにより、モックを実現しています。
  • 今回はstatus codeが正常であることだけが分かればいいテストにするので、GetArticleService()の返り値はnilにしています。

実際にテストを実行してみます。

terminal
$ go test -v
=== RUN   TestControllerSuite
=== RUN   TestControllerSuite/TestGetArticleController
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

--- PASS: TestControllerSuite (0.00s)
    --- PASS: TestControllerSuite/TestGetArticleController (0.00s)
PASS
ok      article/api/controller  0.044s

passしました。


全体像を把握したい場合は、以下のgithubをご参照ください。
https://github.com/jpskgc/article/tree/master/api

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away