Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tools/goctl/api/gogen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ func DoGenProjectWithModule(apiFile, dir, moduleName, style string, withTest boo
if withTest {
logx.Must(genHandlersTest(dir, rootPkg, projectPkg, cfg, api))
logx.Must(genLogicTest(dir, rootPkg, projectPkg, cfg, api))
logx.Must(genServiceContextTest(dir, rootPkg, projectPkg, cfg, api))
logx.Must(genIntegrationTest(dir, rootPkg, projectPkg, cfg, api))
}

if err := backupAndSweep(apiFile); err != nil {
Expand Down
42 changes: 42 additions & 0 deletions tools/goctl/api/gogen/genintegrationtest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package gogen

import (
_ "embed"

"github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
"github.com/zeromicro/go-zero/tools/goctl/util/format"
)

//go:embed integration_test.tpl
var integrationTestTemplate string

func genIntegrationTest(dir, rootPkg, projectPkg string, cfg *config.Config, api *spec.ApiSpec) error {
serviceName := api.Service.Name
if len(serviceName) == 0 {
serviceName = "server"
}

filename, err := format.FileNamingFormat(cfg.NamingFormat, serviceName)
if err != nil {
return err
}

return genFile(fileGenConfig{
dir: dir,
subdir: "",
filename: filename + "_test.go",
templateName: "integrationTestTemplate",
category: category,
templateFile: integrationTestTemplateFile,
builtinTemplate: integrationTestTemplate,
data: map[string]any{
"projectPkg": projectPkg,
"serviceName": serviceName,
"version": version.BuildVersion,
"hasRoutes": len(api.Service.Routes()) > 0,
"routes": api.Service.Routes(),
},
})
}
34 changes: 34 additions & 0 deletions tools/goctl/api/gogen/gensvctest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package gogen

import (
_ "embed"

"github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/zeromicro/go-zero/tools/goctl/internal/version"
"github.com/zeromicro/go-zero/tools/goctl/util/format"
)

//go:embed svc_test.tpl
var svcTestTemplate string

func genServiceContextTest(dir, rootPkg, projectPkg string, cfg *config.Config, api *spec.ApiSpec) error {
filename, err := format.FileNamingFormat(cfg.NamingFormat, contextFilename)
if err != nil {
return err
}

return genFile(fileGenConfig{
dir: dir,
subdir: contextDir,
filename: filename + "_test.go",
templateName: "svcTestTemplate",
category: category,
templateFile: svcTestTemplateFile,
builtinTemplate: svcTestTemplate,
data: map[string]any{
"projectPkg": projectPkg,
"version": version.BuildVersion,
},
})
}
120 changes: 120 additions & 0 deletions tools/goctl/api/gogen/integration_test.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Code scaffolded by goctl. Safe to edit.
// goctl {{.version}}

package main

import (
"net/http"
"net/http/httptest"
"testing"
"time"

"{{.projectPkg}}/internal/config"
"{{.projectPkg}}/internal/handler"
"{{.projectPkg}}/internal/svc"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zeromicro/go-zero/rest"
)

func TestMain(m *testing.M) {
// TODO: Add setup/teardown logic here if needed
m.Run()
}

func TestServerIntegration(t *testing.T) {
// Create test server
c := config.Config{
RestConf: rest.RestConf{
Host: "127.0.0.1",
Port: 0, // Use random available port
},
}

server := rest.MustNewServer(c.RestConf)
defer server.Stop()

ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)

// Start server in background
go func() {
server.Start()
}()

// Wait for server to start
time.Sleep(100 * time.Millisecond)

tests := []struct {
name string
method string
path string
body string
expectedStatus int
setup func()
}{
{
name: "health check",
method: "GET",
path: "/health",
expectedStatus: http.StatusNotFound, // Adjust based on actual routes
setup: func() {},
},
{{if .hasRoutes}}{{range .routes}}{
name: "{{.Method}} {{.Path}}",
method: "{{.Method}}",
path: "{{.Path}}",
expectedStatus: http.StatusOK, // TODO: Adjust expected status
setup: func() {
// TODO: Add setup logic for this endpoint
},
},
{{end}}{{end}}{
name: "not found route",
method: "GET",
path: "/nonexistent",
expectedStatus: http.StatusNotFound,
setup: func() {},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.setup()

req, err := http.NewRequest(tt.method, tt.path, nil)
require.NoError(t, err)

rr := httptest.NewRecorder()
server.ServeHTTP(rr, req)

assert.Equal(t, tt.expectedStatus, rr.Code)

// TODO: Add response body assertions
t.Logf("Response: %s", rr.Body.String())
})
}
}

func TestServerLifecycle(t *testing.T) {
c := config.Config{
RestConf: rest.RestConf{
Host: "127.0.0.1",
Port: 0,
},
}

server := rest.MustNewServer(c.RestConf)

// Test server can start and stop without errors
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)

// In a real integration test, you might start the server in a goroutine
// and test actual HTTP requests, but for scaffolding we keep it simple
server.Stop()

// TODO: Add more lifecycle tests as needed
assert.True(t, true, "Server lifecycle test passed")
}
17 changes: 17 additions & 0 deletions tools/goctl/api/gogen/jwt.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
type Request {
Name string `path:"name,options=you|me"`
}

type Response {
Message string `json:"message"`
}

@server(
jwt: Auth
jwtTransition: Trans
middleware: TokenValidate
)
service A-api {
@handler GreetHandler
get /greet/from/:name(Request) returns (Response)
}
60 changes: 60 additions & 0 deletions tools/goctl/api/gogen/svc_test.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Code scaffolded by goctl. Safe to edit.
// goctl {{.version}}

package svc

import (
"testing"

"{{.projectPkg}}/internal/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewServiceContext(t *testing.T) {
tests := []struct {
name string
config config.Config
setup func() config.Config
}{
{
name: "default config",
setup: func() config.Config {
return config.Config{}
},
},
{
name: "valid config",
setup: func() config.Config {
return config.Config{
// TODO: Add valid config values here
}
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := tt.setup()
svcCtx := NewServiceContext(c)

// Basic assertions
require.NotNil(t, svcCtx)
assert.Equal(t, c, svcCtx.Config)

// TODO: Add additional assertions for middleware and dependencies
})
}
}

func TestServiceContext_Initialization(t *testing.T) {
c := config.Config{}
svcCtx := NewServiceContext(c)

// Verify service context is properly initialized
assert.NotNil(t, svcCtx)
assert.Equal(t, c, svcCtx.Config)

// TODO: Add tests for middleware initialization if any
// TODO: Add tests for external dependencies if any
}
4 changes: 4 additions & 0 deletions tools/goctl/api/gogen/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const (
routesTemplateFile = "routes.tpl"
routesAdditionTemplateFile = "route-addition.tpl"
typesTemplateFile = "types.tpl"
svcTestTemplateFile = "svc_test.tpl"
integrationTestTemplateFile = "integration_test.tpl"
)

var templates = map[string]string{
Expand All @@ -39,6 +41,8 @@ var templates = map[string]string{
routesTemplateFile: routesTemplate,
routesAdditionTemplateFile: routesAdditionTemplate,
typesTemplateFile: typesTemplate,
svcTestTemplateFile: svcTestTemplate,
integrationTestTemplateFile: integrationTestTemplate,
}

// Category returns the category of the api files.
Expand Down
Loading