ejemplos de test unitarios en go usando bun router
- Instalar go y configurar las rutas necesarias como variables de entorno
- Instalar vs studio code o editor de preferencia
- Instalar go tools y el plugin de go
- Iniciar repositorio
-
Iniciar modulo
go mod init "nombre del modulo"
-
Para crear nuestro go.sum(archivo que registrará los requerimientos y dependencias) go mod tidy
-
Crear arhivo main.go
package main
func main() {
}
-
Vamos a descargar el enrutador http que usaremos
go get github.com/uptrace/bunrouter
-
Agregamos el import al main
import "github.com/uptrace/bunrouter"
- Creamos la instancia al router que nos proporciona esta librería
router := bunrouter.New()
-
Ver documentación oficial Creando un go router
-
Según la documentación oficial nos recomiendan ordenar los endpoint en grupos
router.WithGroup("/api/categories", func(group *bunrouter.Group) {
// /api/categories/:category/items
group.WithGroup("/:category/items", func(group *bunrouter.Group) {})
// /api/categories/archive
group.WithGroup("/archive", func(group *bunrouter.Group) {})
})
- Agregaremos el archivo handler.go
package main
import (
"net/http"
"github.com/uptrace/bunrouter"
)
type handler struct {
}
func (h handler)GetById(w http.ResponseWriter, req bunrouter.Request) error {
return nil
}
func (h handler)Create(w http.ResponseWriter, req bunrouter.Request) error {
return nil
}
func (h handler)Delete(w http.ResponseWriter, req bunrouter.Request) error {
return nil
}
func (h handler)Update(w http.ResponseWriter, req bunrouter.Request) error {
return nil
}
- Actualizamos el main para incluir el import del handler y especificar los endpoint - El método, la ruta y los parametros
package main
import (
"go-tests/handler"
"github.com/uptrace/bunrouter"
)
func main() {
h:= &handler.Controlador{}
router := bunrouter.New()
router.WithGroup("/api/categories", func(group *bunrouter.Group) {
// /api/categories/:category/items
group.WithGroup("/:category/items", func(group *bunrouter.Group) {
group.GET("/:id", h.GetById)
group.POST("", h.Create)
group.PATCH("/:id", h.Update)
group.DELETE("/:id", h.Delete)
})
// /api/categories/archive
group.WithGroup("/archive", func(group *bunrouter.Group) {})
})
}
- En el handler del metodo getbyid agregamos para imprimir en consola detalles de la request
fmt.Println(req.Method, req.Route(), req.Params().Map())
- Podemos usar curl o armar un postman ((o cliente http a elección))
curl --location 'http://localhost:9999/api/categories/category/items/1'
- Agregar la línea en main.go donde levantaremos el servidor
log.Println(http.ListenAndServe(":9999", router))
-
Ejecutar con go run main.go y realizar la request
-
Debiesemos ver en consola
GET /api/categories/:category/items/:id map[category:category id:1]
- Vamos a modificar el handler agregando un slice de categorias
type Category struct{
Id int
Name string
}
var categories = []Category{Category{
Id: 1,
Name: "News",
}}
func (h Controlador)GetById(w http.ResponseWriter, req bunrouter.Request) error {
// req embeds *http.Request and has all the same fields and methods
fmt.Println(req.Method, req.Route(), req.Params().Map())
id := req.Params.ByName("id")
cat :=""
for i := range categories {
if fmt.Sprint(categories[i].Id) ==id {
// Found!
cat = categories[i].Name
}
}
if cat ==""{
w.WriteHeader(404)
return nil
}
//caso feliz
w.WriteHeader(200)
return nil
}
- Agregamos el archivo handler_test.go
package handler_test
import "testing"
func TestHandlerGetById(t *testing.T) {
}
func TestHandlerCreate(t *testing.T) {
}
func TestHandlerGetDelete(t *testing.T) {
}
func TestHandlerGetUpdate(t *testing.T) {
}
- Agregar libreria para asserts
go get "github.com/stretchr/testify/assert"
- Actualizamos con los test
var router = bunrouter.New()
func TestHandlerGetById(t *testing.T) {
c :=&handler.Controlador{}
router.GET("/api/categories/category/items/:id", c.GetById)
t.Run("Happy Path 200 status code", func(t *testing.T) {
w := httptest.NewRecorder()
baseURL, _ := url.Parse("/api/categories/category/items/1")
params := url.Values{}
params.Add("id", "1")
baseURL.RawQuery = params.Encode()
req, _ := http.NewRequest(http.MethodGet, baseURL.String(), nil)
err := router.ServeHTTPError(w, req)
assert.Equal(t, 200, w.Code)
require.NoError(t, err)
})
t.Run("UnHappy Path 404 status code", func(t *testing.T) {
w := httptest.NewRecorder()
baseURL, _ := url.Parse("/api/categories/category/items/2")
params := url.Values{}
params.Add("id", "2")
baseURL.RawQuery = params.Encode()
req, _ := http.NewRequest(http.MethodGet, baseURL.String(), nil)
err := router.ServeHTTPError(w, req)
assert.Equal(t, 404, w.Code)
require.NoError(t, err)
})
}