Files
api_tmpl/internal/handlers/grpc/rpc_update_user_test.go
2026-01-08 01:15:07 +00:00

185 lines
5.3 KiB
Go

package gapi
import (
"context"
"testing"
"time"
"github.com/FernandoJVideira/simple_bank/internal/auth"
db "github.com/FernandoJVideira/simple_bank/internal/db/sqlc"
"github.com/FernandoJVideira/simple_bank/internal/service"
mocksvc "github.com/FernandoJVideira/simple_bank/internal/service/mock"
"github.com/FernandoJVideira/simple_bank/pb"
"github.com/FernandoJVideira/simple_bank/pkg/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestUpdateUserRPC(t *testing.T) {
user, _ := randomUser(t)
newName := testutil.RandomOwner()
newEmail := testutil.RandomEmail()
invalidEmail := "invalid-email-format"
testCases := []struct {
name string
req *pb.UpdateUserRequest
buildStubs func(userService *mocksvc.MockUserService)
buildContext func(t *testing.T, tokenMaker auth.Maker) context.Context
checkResponse func(t *testing.T, res *pb.UpdateUserResponse, err error)
}{
{
name: "OK",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
},
buildStubs: func(userService *mocksvc.MockUserService) {
arg := service.UserUpdateRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
}
updatedUser := db.User{
Username: user.Username,
HashedPassword: user.HashedPassword,
FullName: newName,
Email: newEmail,
}
userService.EXPECT().
UpdateUser(gomock.Any(), gomock.Eq(arg)).
Times(1).
Return(&updatedUser, nil)
},
buildContext: func(t *testing.T, tokenMaker auth.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, user.Role, time.Minute)
},
checkResponse: func(t *testing.T, res *pb.UpdateUserResponse, err error) {
require.NoError(t, err)
require.NotNil(t, res)
updatedUser := res.GetUser()
require.Equal(t, user.Username, updatedUser.Username)
require.Equal(t, newName, updatedUser.FullName)
require.Equal(t, newEmail, updatedUser.Email)
},
}, {
name: "UserNotFound",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(1).
Return(nil, db.ErrRecordNotFound)
},
buildContext: func(t *testing.T, tokenMaker auth.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, user.Role, time.Minute)
},
checkResponse: func(t *testing.T, res *pb.UpdateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.NotFound)
},
}, {
name: "ExpiredToken",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(0)
},
buildContext: func(t *testing.T, tokenMaker auth.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, user.Role, -time.Minute)
},
checkResponse: func(t *testing.T, res *pb.UpdateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.Unauthenticated)
},
}, {
name: "NoAuthorizationHeader",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(0)
},
buildContext: func(t *testing.T, tokenMaker auth.Maker) context.Context {
return context.Background()
},
checkResponse: func(t *testing.T, res *pb.UpdateUserResponse, err error) {
require.Error(t, err)
st, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, st.Code(), codes.Unauthenticated)
},
}, {
name: "InvalidEmail",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &invalidEmail,
},
buildStubs: func(userService *mocksvc.MockUserService) {
userService.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(0)
},
buildContext: func(t *testing.T, tokenMaker auth.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, user.Role, time.Minute)
},
checkResponse: func(t *testing.T, res *pb.UpdateUserResponse, 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)
ctx := tc.buildContext(t, s.tokenMaker)
// Call UpdateUser RPC
res, err := s.UpdateUser(ctx, tc.req)
tc.checkResponse(t, res, err)
})
}
}