My project is split into three main components: controllers, services, and models. When a route is queried via the URI, the controllers are called, which then call the services to interact with the models, which then interact with the database via gorm.
I am trying to write unit tests for the controllers, but I'm having a hard time understanding how to properly mock the services layer while mocking the gin layer. I can get a mocked gin context, but I'm not able to mock the service layer within my controller method. Below is my code:
resourceController.go
package controllers
import (
"MyApi/models"
"MyApi/services"
"github.com/gin-gonic/gin"
"net/http"
)
func GetResourceById(c *gin.Context) {
id := c.Param("id")
resource, err := services.GetResourceById(id)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": http.StatusBadRequest, "message": err})
return
} else if resource.ID == 0 {
c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": "Resource with id:"+id+" does not exist"})
return
}
c.JSON(http.StatusOK, gin.H{
"id": resource.ID,
"data1": resource.Data1,
"data2": resource.Data2,
})
}
I want to test that the c.JSON is returning with the proper http
status and other data. I need to mock the id
variable, err
variable, and c.JSON
function, but when I try to set the c.JSON
function in the test to my new function, I get an error saying Cannot assign to c.JSON
.
Below is my attempt at writing a test:
resourceController_test.go
package controllers
import (
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"net/http/httptest"
"testing"
)
func TestGetResourceById(t *testing.T) {
var status int
var body interface{}
c, _ := gin.CreateTestContext(httptest.NewRecorder())
c.JSON = func(stat int, object interface{}) {
status = stat
body = object
}
GetResourceById(c)
assert.Equal(t, 4, 4)
}
How do I properly write a unit test to test whether the c.JSON is returning the proper values?