Skip to content

Commit

Permalink
add unit tests for the update_user_rpc (techschool#88)
Browse files Browse the repository at this point in the history
Co-authored-by: phamlequang <phamlequang@gmail.com>
  • Loading branch information
techschool and phamlequang authored Apr 2, 2023
1 parent 81749ac commit bdfe8e7
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
18 changes: 18 additions & 0 deletions gapi/main_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package gapi

import (
"context"
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
db "github.com/techschool/simplebank/db/sqlc"
"github.com/techschool/simplebank/token"
"github.com/techschool/simplebank/util"
"github.com/techschool/simplebank/worker"
"google.golang.org/grpc/metadata"
)

func newTestServer(t *testing.T, store db.Store, taskDistributor worker.TaskDistributor) *Server {
Expand All @@ -21,3 +25,17 @@ func newTestServer(t *testing.T, store db.Store, taskDistributor worker.TaskDist

return server
}

func newContextWithBearerToken(t *testing.T, tokenMaker token.Maker, username string, duration time.Duration) context.Context {
accessToken, _, err := tokenMaker.CreateToken(username, duration)
require.NoError(t, err)

bearerToken := fmt.Sprintf("%s %s", authorizationBearer, accessToken)
md := metadata.MD{
authorizationHeader: []string{
bearerToken,
},
}

return metadata.NewIncomingContext(context.Background(), md)
}
186 changes: 186 additions & 0 deletions gapi/rpc_update_user_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package gapi

import (
"context"
"database/sql"
"testing"
"time"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
mockdb "github.com/techschool/simplebank/db/mock"
db "github.com/techschool/simplebank/db/sqlc"
"github.com/techschool/simplebank/pb"
"github.com/techschool/simplebank/token"
"github.com/techschool/simplebank/util"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func TestUpdateUserAPI(t *testing.T) {
user, _ := randomUser(t)

newName := util.RandomOwner()
newEmail := util.RandomEmail()
invalidEmail := "invalid-email"

testCases := []struct {
name string
req *pb.UpdateUserRequest
buildStubs func(store *mockdb.MockStore)
buildContext func(t *testing.T, tokenMaker token.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(store *mockdb.MockStore) {
arg := db.UpdateUserParams{
Username: user.Username,
FullName: sql.NullString{
String: newName,
Valid: true,
},
Email: sql.NullString{
String: newEmail,
Valid: true,
},
}
updatedUser := db.User{
Username: user.Username,
HashedPassword: user.HashedPassword,
FullName: newName,
Email: newEmail,
PasswordChangedAt: user.PasswordChangedAt,
CreatedAt: user.CreatedAt,
IsEmailVerified: user.IsEmailVerified,
}
store.EXPECT().
UpdateUser(gomock.Any(), gomock.Eq(arg)).
Times(1).
Return(updatedUser, nil)
},
buildContext: func(t *testing.T, tokenMaker token.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, 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(store *mockdb.MockStore) {
store.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(1).
Return(db.User{}, sql.ErrNoRows)
},
buildContext: func(t *testing.T, tokenMaker token.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, 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, codes.NotFound, st.Code())
},
},
{
name: "InvalidEmail",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &invalidEmail,
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(0)
},
buildContext: func(t *testing.T, tokenMaker token.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, 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, codes.InvalidArgument, st.Code())
},
},
{
name: "ExpiredToken",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(0)
},
buildContext: func(t *testing.T, tokenMaker token.Maker) context.Context {
return newContextWithBearerToken(t, tokenMaker, user.Username, -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, codes.Unauthenticated, st.Code())
},
},
{
name: "NoAuthorization",
req: &pb.UpdateUserRequest{
Username: user.Username,
FullName: &newName,
Email: &newEmail,
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
UpdateUser(gomock.Any(), gomock.Any()).
Times(0)
},
buildContext: func(t *testing.T, tokenMaker token.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, codes.Unauthenticated, st.Code())
},
},
}

for i := range testCases {
tc := testCases[i]

t.Run(tc.name, func(t *testing.T) {
storeCtrl := gomock.NewController(t)
defer storeCtrl.Finish()
store := mockdb.NewMockStore(storeCtrl)

tc.buildStubs(store)
server := newTestServer(t, store, nil)

ctx := tc.buildContext(t, server.tokenMaker)
res, err := server.UpdateUser(ctx, tc.req)
tc.checkResponse(t, res, err)
})
}
}

0 comments on commit bdfe8e7

Please sign in to comment.