Files
api_tmpl/internal/handlers/grpc/rpc_create_user_test.go
FernandoJVideira c4ee0ce4dc chore: rename simple_bank to api_tmpl and clean up for template use
Rename the module, proto service, and all identifiers from simple_bank/
SimpleBank to api_tmpl/ApiTmpl, and regenerate the gRPC/gateway/swagger/
mock code accordingly.

- Scrub real secrets (SMTP password, auth token secret) from api.env/
  api_test.env, untrack them, and add api.env.example/api_test.env.example
- Remove committed build artifacts (tmp/main, tmp/build-errors.log,
  dbml-error.log) and gitignore them going forward
- Fix Dockerfile paths (build target, migrations copy) that referenced a
  stale project layout
- Rewrite README to match the actual cmd/ + internal/ structure and add a
  "using this as a template" section
2026-08-25 03:02:37 +01:00

183 lines
4.8 KiB
Go

package gapi
import (
"context"
"database/sql"
"testing"
db "github.com/FernandoJVideira/api_tmpl/internal/db/sqlc"
"github.com/FernandoJVideira/api_tmpl/internal/domain/role"
"github.com/FernandoJVideira/api_tmpl/internal/security"
"github.com/FernandoJVideira/api_tmpl/internal/service"
mocksvc "github.com/FernandoJVideira/api_tmpl/internal/service/mock"
"github.com/FernandoJVideira/api_tmpl/pb"
"github.com/FernandoJVideira/api_tmpl/pkg/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func randomUser(t *testing.T) (user db.User, password string) {
password = testutil.RandomString(6)
hashedPassword, err := security.HashPassword(password)
if err != nil {
t.Fatal(err)
}
user = db.User{
Username: testutil.RandomOwner(),
HashedPassword: hashedPassword,
Role: role.MemberRole,
FullName: testutil.RandomOwner(),
Email: testutil.RandomEmail(),
}
return
}
func TestCreateUserRPC(t *testing.T) {
user, password := randomUser(t)
testCases := []struct {
name string
req *pb.CreateUserRequest
buildStubs func(userService *mocksvc.MockUserService)
checkResponse func(t *testing.T, res *pb.CreateUserResponse, err error)
}{
{
name: "OK",
req: &pb.CreateUserRequest{
Username: user.Username,
Password: password,
FullName: user.FullName,
Email: user.Email,
},
buildStubs: func(userService *mocksvc.MockUserService) {
arg := service.RegisterUserRequest{
Username: user.Username,
Password: password,
FullName: user.FullName,
Email: user.Email,
}
userService.EXPECT().
CreateUser(gomock.Any(), gomock.Eq(arg)).
Times(1).
Return(&service.RegisterUserResponse{
User: user,
}, nil)
},
checkResponse: func(t *testing.T, res *pb.CreateUserResponse, err error) {
require.NoError(t, err)
require.NotNil(t, res)
require.Equal(t, user.Username, res.User.Username)
require.Equal(t, user.FullName, res.User.FullName)
require.Equal(t, user.Email, res.User.Email)
require.NotEmpty(t, res.User.CreatedAt)
},
},
{
name: "InternalError",
req: &pb.CreateUserRequest{
Username: user.Username,
Password: password,
FullName: user.FullName,
Email: user.Email,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
CreateUser(gomock.Any(), gomock.Any()).
Times(1).
Return(nil, sql.ErrConnDone)
},
checkResponse: func(t *testing.T, res *pb.CreateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.Internal)
},
},
{
name: "DuplicateUsername",
req: &pb.CreateUserRequest{
Username: user.Username,
Password: password,
FullName: user.FullName,
Email: user.Email,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
CreateUser(gomock.Any(), gomock.Any()).
Times(1).
Return(nil, db.ErrUniqueViolation)
},
checkResponse: func(t *testing.T, res *pb.CreateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.AlreadyExists)
},
},
{
name: "InvalidEmail",
req: &pb.CreateUserRequest{
Username: user.Username,
Password: password,
FullName: user.FullName,
Email: "invalid-email",
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
CreateUser(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(t *testing.T, res *pb.CreateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.InvalidArgument)
},
},
{
name: "PasswordTooShort",
req: &pb.CreateUserRequest{
Username: user.Username,
Password: "short",
FullName: user.FullName,
Email: user.Email,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
CreateUser(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(t *testing.T, res *pb.CreateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.InvalidArgument)
},
},
}
for i := range testCases {
tc := testCases[i]
t.Run(tc.name, func(t *testing.T) {
userCtrl := gomock.NewController(t)
defer userCtrl.Finish()
userService := mocksvc.NewMockUserService(userCtrl)
tc.buildStubs(userService)
// Start test server and send request
s := newTestServer(t, nil, nil, userService, nil)
res, err := s.CreateUser(context.Background(), tc.req)
tc.checkResponse(t, res, err)
})
}
}