github.com/lovung/GoCleanArchitecture@v0.0.0-20210302152432-50d91fd29f9f/app/internal/interface/restful/handler/auth_handler_test.go (about)

     1  package handler
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/gin-gonic/gin"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/google/go-cmp/cmp"
    15  	"github.com/lovung/GoCleanArchitecture/app/internal/interface/restful/middleware"
    16  	"github.com/lovung/GoCleanArchitecture/app/internal/interface/restful/presenter"
    17  	"github.com/lovung/GoCleanArchitecture/app/internal/usecase"
    18  	"github.com/lovung/GoCleanArchitecture/app/internal/usecase/dto"
    19  	"github.com/lovung/GoCleanArchitecture/app/internal/usecase/mockusecase"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestNewAuthHandler(t *testing.T) {
    24  	type args struct {
    25  		userUseCase usecase.UserUseCase
    26  	}
    27  	t.Parallel()
    28  	mockCtrl := gomock.NewController(t)
    29  	defer mockCtrl.Finish()
    30  	mUserUseCase := mockusecase.NewMockUserUseCase(mockCtrl)
    31  
    32  	testCases := []struct {
    33  		name string
    34  		args args
    35  		want AuthHandler
    36  	}{
    37  		{
    38  			args: args{
    39  				userUseCase: mUserUseCase,
    40  			},
    41  			want: AuthHandler{
    42  				BaseHandler: BaseHandler{},
    43  				userUseCase: mUserUseCase,
    44  			},
    45  		},
    46  	}
    47  	for _, tt := range testCases {
    48  		t.Run(tt.name, func(t *testing.T) {
    49  			if got := NewAuthHandler(tt.args.userUseCase); !reflect.DeepEqual(got, tt.want) {
    50  				t.Errorf("NewAuthHandler() = %v, want %v", got, tt.want)
    51  			}
    52  		})
    53  	}
    54  }
    55  
    56  func TestAuthHandler_Register(t *testing.T) {
    57  	type fields struct {
    58  		BaseHandler BaseHandler
    59  		userUseCase usecase.UserUseCase
    60  	}
    61  	type args struct {
    62  		// ctx *gin.Context
    63  		req presenter.RegisterRequest
    64  	}
    65  	type wants struct {
    66  		httpCode int
    67  		body     interface{}
    68  	}
    69  	t.Parallel()
    70  	mockCtrl := gomock.NewController(t)
    71  	defer mockCtrl.Finish()
    72  	mUserUseCase := mockusecase.NewMockUserUseCase(mockCtrl)
    73  	_fields := fields{
    74  		BaseHandler: BaseHandler{},
    75  		userUseCase: mUserUseCase,
    76  	}
    77  
    78  	runFunc := func(t *testing.T, fields fields, args args, w wants) {
    79  		hdl := &AuthHandler{
    80  			BaseHandler: fields.BaseHandler,
    81  			userUseCase: fields.userUseCase,
    82  		}
    83  		// Switch to test mode so you don't get such noisy output
    84  		gin.SetMode(gin.TestMode)
    85  
    86  		// Create a response recorder so you can inspect the response
    87  		resp := httptest.NewRecorder()
    88  		r := gin.Default()
    89  		// Setup your router, just like you did in your main function, and
    90  		// register your routes
    91  		r.Use(middleware.JSONWriterMiddleware)
    92  		r.POST("/register", hdl.Register)
    93  		// Create the mock request you'd like to test. Make sure the second argument
    94  		// here is the same as one of the routes you defined in the router setup
    95  		// block!
    96  		body, err := json.Marshal(args.req)
    97  		assert.NoError(t, err)
    98  		req, err := http.NewRequest(http.MethodPost, "/register", bytes.NewReader(body))
    99  		assert.NoError(t, err)
   100  
   101  		// Perform the request
   102  		r.ServeHTTP(resp, req)
   103  		assert.Equal(t, w.httpCode, resp.Code)
   104  		if diff := cmp.Diff(w.body, resp.Body.String()); diff != "" {
   105  			t.Errorf("Diff body = %v", diff)
   106  			assert.Equal(t, w.body, resp.Body.String())
   107  		}
   108  	}
   109  	t.Run("#1: Error when binding", func(t *testing.T) {
   110  		runFunc(t, _fields,
   111  			args{
   112  				req: presenter.RegisterRequest{
   113  					Username: "username",
   114  				},
   115  			},
   116  			wants{
   117  				httpCode: 400,
   118  				body:     "{\"meta\":{\"code\":400,\"message\":\"error when binding the request\"},\"errors\":[{\"code\":422,\"detail\":\"Key: 'RegisterRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag\",\"source\":{\"pointer\":\"RegisterRequest.Password\",\"parameter\":\"Password\"}}]}",
   119  			})
   120  	})
   121  	t.Run("#2: Error when binding username", func(t *testing.T) {
   122  		runFunc(t, _fields,
   123  			args{
   124  				req: presenter.RegisterRequest{
   125  					Password: "password",
   126  				},
   127  			},
   128  			wants{
   129  				httpCode: 400,
   130  				body:     "{\"meta\":{\"code\":400,\"message\":\"error when binding the request\"},\"errors\":[{\"code\":422,\"detail\":\"Key: 'RegisterRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag\",\"source\":{\"pointer\":\"RegisterRequest.Username\",\"parameter\":\"Username\"}}]}",
   131  			})
   132  	})
   133  	t.Run("#3: Call use case got error", func(t *testing.T) {
   134  		mUserUseCase.EXPECT().Create(gomock.Any(), dto.CreateUserRequest{
   135  			Password: "password",
   136  			Username: "username",
   137  		}).Return(dto.OneUserResponse{}, errors.New("error"))
   138  		runFunc(t, _fields,
   139  			args{
   140  				req: presenter.RegisterRequest{
   141  					Username: "username",
   142  					Password: "password",
   143  				},
   144  			},
   145  			// TODO: Update wants when implementing the JSONWriterMiddleware
   146  			// to handle the App Error (error from business logic)
   147  			wants{
   148  				httpCode: 204,
   149  				body:     "",
   150  			})
   151  	})
   152  	t.Run("#4: Success", func(t *testing.T) {
   153  		mUserUseCase.EXPECT().Create(gomock.Any(), dto.CreateUserRequest{
   154  			Password: "password",
   155  			Username: "username",
   156  		}).Return(dto.OneUserResponse{
   157  			ID:       "id",
   158  			Username: "username",
   159  		}, nil)
   160  		runFunc(t, _fields,
   161  			args{
   162  				req: presenter.RegisterRequest{
   163  					Username: "username",
   164  					Password: "password",
   165  				},
   166  			},
   167  			wants{
   168  				httpCode: 201,
   169  				body:     "{\"meta\":{\"code\":201},\"data\":{\"id\":\"id\",\"username\":\"username\"}}",
   170  			})
   171  	})
   172  }
   173  
   174  // func TestAuthHandler_RegisterWithTransaction(t *testing.T) {
   175  // 	type fields struct {
   176  // 		BaseHandler BaseHandler
   177  // 		userUseCase usecase.UserUseCase
   178  // 	}
   179  // 	type args struct {
   180  // 		// ctx *gin.Context
   181  // 		req presenter.RegisterRequest
   182  // 	}
   183  // 	type wants struct {
   184  // 		httpCode int
   185  // 		body     interface{}
   186  // 	}
   187  // 	t.Parallel()
   188  // 	mockCtrl := gomock.NewController(t)
   189  // 	defer mockCtrl.Finish()
   190  // 	mUserUseCase := mockusecase.NewMockUserUseCase(mockCtrl)
   191  // 	mTransactionManager := mocktrans.NewMockManager(mockCtrl)
   192  // 	gDB, _, err := tests.OpenDBConnection()
   193  // 	logger.Init(true)
   194  // 	assert.NoError(t, err)
   195  // 	_fields := fields{
   196  // 		BaseHandler: BaseHandler{},
   197  // 		userUseCase: mUserUseCase,
   198  // 	}
   199  
   200  // 	runFunc := func(t *testing.T, fields fields, args args, w wants) {
   201  // 		hdl := &AuthHandler{
   202  // 			BaseHandler: fields.BaseHandler,
   203  // 			userUseCase: fields.userUseCase,
   204  // 		}
   205  // 		txnMw := middleware.NewTransactionMiddleware(mTransactionManager)
   206  // 		// Switch to test mode so you don't get such noisy output
   207  // 		gin.SetMode(gin.TestMode)
   208  
   209  // 		// Create a response recorder so you can inspect the response
   210  // 		resp := httptest.NewRecorder()
   211  // 		ctx, r := gin.CreateTestContext(resp)
   212  // 		// Setup your router, just like you did in your main function, and
   213  // 		// register your routes
   214  // 		r.Use(middleware.JSONWriterMiddleware)
   215  // 		r.Use(txnMw.StartRequest)
   216  // 		r.Use(txnMw.EndRequest)
   217  // 		r.POST("/register", hdl.Register)
   218  // 		// Create the mock request you'd like to test. Make sure the second argument
   219  // 		// here is the same as one of the routes you defined in the router setup
   220  // 		// block!
   221  // 		body, err := json.Marshal(args.req)
   222  // 		assert.NoError(t, err)
   223  // 		req, err := http.NewRequest(http.MethodPost, "/register", bytes.NewReader(body))
   224  // 		assert.NoError(t, err)
   225  
   226  // 		tx := gDB.Begin()
   227  // 		newCtx := appctx.SetValue(ctx.Request.Context(), appctx.TransactionContextKey, tx)
   228  
   229  // 		mTransactionManager.EXPECT().TxnBegin(gomock.Any()).Return(newCtx)
   230  // 		mTransactionManager.EXPECT().TxnRollback(gomock.Any()).Return(nil)
   231  // 		// Perform the request
   232  // 		r.ServeHTTP(resp, req)
   233  // 		assert.Equal(t, w.httpCode, resp.Code)
   234  // 		if diff := cmp.Diff(w.body, resp.Body.String()); diff != "" {
   235  // 			t.Errorf("Diff body = %v", diff)
   236  // 			assert.Equal(t, w.body, resp.Body.String())
   237  // 		}
   238  // 	}
   239  // 	t.Run("#1: Error when binding", func(t *testing.T) {
   240  // 		runFunc(t, _fields,
   241  // 			args{
   242  // 				req: presenter.RegisterRequest{
   243  // 					Username: "username",
   244  // 				},
   245  // 			},
   246  // 			wants{
   247  // 				httpCode: 400,
   248  // 				body:     "{\"meta\":{\"code\":400,\"message\":\"error when binding the request\"},\"errors\":[{\"code\":422,\"detail\":\"Key: 'RegisterRequest.Password' Error:Field validation for 'Password' failed on the 'required' tag\",\"source\":{\"pointer\":\"RegisterRequest.Password\",\"parameter\":\"Password\"}}]}",
   249  // 			})
   250  // 	})
   251  // t.Run("#2: Error when binding username", func(t *testing.T) {
   252  // 	ctx := context.Background()
   253  // 	tx := gDB.Begin()
   254  // 	ctx = appctx.SetValue(ctx, appctx.TransactionContextKey, tx)
   255  // 	mTransactionManager.EXPECT().TxnBegin(gomock.Any()).Return(ctx)
   256  // 	mTransactionManager.EXPECT().TxnRollback(gomock.Any()).Return(nil)
   257  // 	runFunc(t, _fields,
   258  // 		args{
   259  // 			req: presenter.RegisterRequest{
   260  // 				Password: "password",
   261  // 			},
   262  // 		},
   263  // 		wants{
   264  // 			httpCode: 400,
   265  // 			body:     "{\"meta\":{\"code\":400,\"message\":\"error when binding the request\"},\"errors\":[{\"code\":422,\"detail\":\"Key: 'RegisterRequest.Username' Error:Field validation for 'Username' failed on the 'required' tag\",\"source\":{\"pointer\":\"RegisterRequest.Username\",\"parameter\":\"Username\"}}]}",
   266  // 		})
   267  // })
   268  // t.Run("#3: Call use case got error", func(t *testing.T) {
   269  // 	ctx := context.Background()
   270  // 	tx := gDB.Begin()
   271  // 	ctx = appctx.SetValue(ctx, appctx.TransactionContextKey, tx)
   272  // 	mTransactionManager.EXPECT().TxnBegin(gomock.Any()).Return(ctx)
   273  // 	mTransactionManager.EXPECT().TxnRollback(gomock.Any()).Return(nil)
   274  // 	mUserUseCase.EXPECT().Create(gomock.Any(), dto.CreateUserRequest{
   275  // 		Password: "password",
   276  // 		Username: "username",
   277  // 	}).Return(dto.OneUserResponse{}, errors.New("error"))
   278  // 	runFunc(t, _fields,
   279  // 		args{
   280  // 			req: presenter.RegisterRequest{
   281  // 				Username: "username",
   282  // 				Password: "password",
   283  // 			},
   284  // 		},
   285  // 		// TODO: Update wants when implementing the JSONWriterMiddleware
   286  // 		// to handle the App Error (error from business logic)
   287  // 		wants{
   288  // 			httpCode: 204,
   289  // 			body:     "",
   290  // 		})
   291  // })
   292  // t.Run("#4: Success", func(t *testing.T) {
   293  // 	ctx := context.Background()
   294  // 	tx := gDB.Begin()
   295  // 	ctx = appctx.SetValue(ctx, appctx.TransactionContextKey, tx)
   296  // 	mTransactionManager.EXPECT().TxnBegin(gomock.Any()).Return(ctx)
   297  // 	mTransactionManager.EXPECT().TxnCommit(gomock.Any()).Return(nil)
   298  // 	mTransactionManager.EXPECT().GetTxn(gomock.Any()).Return(tx)
   299  // 	mUserUseCase.EXPECT().Create(gomock.Any(), dto.CreateUserRequest{
   300  // 		Password: "password",
   301  // 		Username: "username",
   302  // 	}).Return(dto.OneUserResponse{
   303  // 		ID:       "id",
   304  // 		Username: "username",
   305  // 	}, nil)
   306  // 	runFunc(t, _fields,
   307  // 		args{
   308  // 			req: presenter.RegisterRequest{
   309  // 				Username: "username",
   310  // 				Password: "password",
   311  // 			},
   312  // 		},
   313  // 		wants{
   314  // 			httpCode: 201,
   315  // 			body:     "{\"meta\":{\"code\":201},\"data\":{\"id\":\"id\",\"username\":\"username\"}}",
   316  // 		})
   317  // })
   318  // }