diff --git a/go.mod b/go.mod index acd4c25..d36d9ba 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/google/uuid v1.6.0 github.com/sirupsen/logrus v1.9.3 github.com/urfave/cli v1.22.15 + go.uber.org/mock v0.4.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 058cd30..b22a121 100644 --- a/go.sum +++ b/go.sum @@ -85,6 +85,8 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM= github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= diff --git a/internal/sbi/api_spyfamily.go b/internal/sbi/api_spyfamily.go index 46117e8..baaa89a 100644 --- a/internal/sbi/api_spyfamily.go +++ b/internal/sbi/api_spyfamily.go @@ -36,7 +36,7 @@ func (s *Server) HTTPSerchSpyFamilyCharacter(c *gin.Context) { targetName := c.Param("Name") if targetName == "" { - c.JSON(http.StatusBadRequest, "No name provided") + c.String(http.StatusBadRequest, "No name provided") return } diff --git a/internal/sbi/api_spyfamily_test.go b/internal/sbi/api_spyfamily_test.go new file mode 100644 index 0000000..a568f85 --- /dev/null +++ b/internal/sbi/api_spyfamily_test.go @@ -0,0 +1,50 @@ +package sbi_test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/andy89923/nf-example/internal/sbi" + "github.com/andy89923/nf-example/pkg/factory" + "github.com/gin-gonic/gin" + "go.uber.org/mock/gomock" +) + +func Test_HTTPSerchSpyFamilyCharacter(t *testing.T) { + mockCtrl := gomock.NewController(t) + nfApp := sbi.NewMocknfApp(mockCtrl) + nfApp.EXPECT().Config().Return(&factory.Config{ + Configuration: &factory.Configuration{ + Sbi: &factory.Sbi{ + Port: 8000, + }, + }, + }).AnyTimes() + server := sbi.NewServer(nfApp, "") + + t.Run("No name provided", func(t *testing.T) { + const EXPECTED_STATUS = http.StatusBadRequest + const EXPECTED_BODY = "No name provided" + + httpRecorder := httptest.NewRecorder() + ginCtx, _ := gin.CreateTestContext(httpRecorder) + + var err error + ginCtx.Request, err = http.NewRequest("GET", "/spyfamily", nil) + if err != nil { + t.Errorf("Failed to create request: %s", err) + return + } + + server.HTTPSerchSpyFamilyCharacter(ginCtx) + + if httpRecorder.Code != EXPECTED_STATUS { + t.Errorf("Expected status code %d, got %d", EXPECTED_STATUS, httpRecorder.Code) + } + + if httpRecorder.Body.String() != EXPECTED_BODY { + t.Errorf("Expected body %s, got %s", EXPECTED_BODY, httpRecorder.Body.String()) + } + }) +} diff --git a/internal/sbi/processor/processor_mock.go b/internal/sbi/processor/processor_mock.go new file mode 100644 index 0000000..9db0e8e --- /dev/null +++ b/internal/sbi/processor/processor_mock.go @@ -0,0 +1,143 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: internal/sbi/processor/processor.go +// +// Generated by this command: +// +// mockgen -source=internal/sbi/processor/processor.go -package=processor +// + +// Package processor is a generated GoMock package. +package processor + +import ( + reflect "reflect" + + context "github.com/andy89923/nf-example/internal/context" + factory "github.com/andy89923/nf-example/pkg/factory" + gomock "go.uber.org/mock/gomock" +) + +// MockProcessorNf is a mock of ProcessorNf interface. +type MockProcessorNf struct { + ctrl *gomock.Controller + recorder *MockProcessorNfMockRecorder +} + +// MockProcessorNfMockRecorder is the mock recorder for MockProcessorNf. +type MockProcessorNfMockRecorder struct { + mock *MockProcessorNf +} + +// NewMockProcessorNf creates a new mock instance. +func NewMockProcessorNf(ctrl *gomock.Controller) *MockProcessorNf { + mock := &MockProcessorNf{ctrl: ctrl} + mock.recorder = &MockProcessorNfMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockProcessorNf) EXPECT() *MockProcessorNfMockRecorder { + return m.recorder +} + +// Config mocks base method. +func (m *MockProcessorNf) Config() *factory.Config { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Config") + ret0, _ := ret[0].(*factory.Config) + return ret0 +} + +// Config indicates an expected call of Config. +func (mr *MockProcessorNfMockRecorder) Config() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Config", reflect.TypeOf((*MockProcessorNf)(nil).Config)) +} + +// Context mocks base method. +func (m *MockProcessorNf) Context() *context.NFContext { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Context") + ret0, _ := ret[0].(*context.NFContext) + return ret0 +} + +// Context indicates an expected call of Context. +func (mr *MockProcessorNfMockRecorder) Context() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MockProcessorNf)(nil).Context)) +} + +// Processor mocks base method. +func (m *MockProcessorNf) Processor() *Processor { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Processor") + ret0, _ := ret[0].(*Processor) + return ret0 +} + +// Processor indicates an expected call of Processor. +func (mr *MockProcessorNfMockRecorder) Processor() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Processor", reflect.TypeOf((*MockProcessorNf)(nil).Processor)) +} + +// SetLogEnable mocks base method. +func (m *MockProcessorNf) SetLogEnable(enable bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLogEnable", enable) +} + +// SetLogEnable indicates an expected call of SetLogEnable. +func (mr *MockProcessorNfMockRecorder) SetLogEnable(enable any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogEnable", reflect.TypeOf((*MockProcessorNf)(nil).SetLogEnable), enable) +} + +// SetLogLevel mocks base method. +func (m *MockProcessorNf) SetLogLevel(level string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLogLevel", level) +} + +// SetLogLevel indicates an expected call of SetLogLevel. +func (mr *MockProcessorNfMockRecorder) SetLogLevel(level any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogLevel", reflect.TypeOf((*MockProcessorNf)(nil).SetLogLevel), level) +} + +// SetReportCaller mocks base method. +func (m *MockProcessorNf) SetReportCaller(reportCaller bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetReportCaller", reportCaller) +} + +// SetReportCaller indicates an expected call of SetReportCaller. +func (mr *MockProcessorNfMockRecorder) SetReportCaller(reportCaller any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetReportCaller", reflect.TypeOf((*MockProcessorNf)(nil).SetReportCaller), reportCaller) +} + +// Start mocks base method. +func (m *MockProcessorNf) Start() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Start") +} + +// Start indicates an expected call of Start. +func (mr *MockProcessorNfMockRecorder) Start() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockProcessorNf)(nil).Start)) +} + +// Terminate mocks base method. +func (m *MockProcessorNf) Terminate() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Terminate") +} + +// Terminate indicates an expected call of Terminate. +func (mr *MockProcessorNfMockRecorder) Terminate() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Terminate", reflect.TypeOf((*MockProcessorNf)(nil).Terminate)) +} diff --git a/internal/sbi/processor/spy_family.go b/internal/sbi/processor/spy_family.go index 64d98d7..eda9036 100644 --- a/internal/sbi/processor/spy_family.go +++ b/internal/sbi/processor/spy_family.go @@ -9,8 +9,8 @@ import ( func (p *Processor) FindSpyFamilyCharacterName(c *gin.Context, targetName string) { if lastName, ok := p.Context().SpyFamilyData[targetName]; ok { - c.JSON(http.StatusOK, fmt.Sprintf("Character: %s %s", targetName, lastName)) + c.String(http.StatusOK, fmt.Sprintf("Character: %s %s", targetName, lastName)) return } - c.JSON(http.StatusNotFound, fmt.Sprintf("[%s] not found in SPYxFAMILY", targetName)) + c.String(http.StatusNotFound, fmt.Sprintf("[%s] not found in SPYxFAMILY", targetName)) } diff --git a/internal/sbi/processor/spy_family_test.go b/internal/sbi/processor/spy_family_test.go new file mode 100644 index 0000000..a8828d6 --- /dev/null +++ b/internal/sbi/processor/spy_family_test.go @@ -0,0 +1,69 @@ +package processor_test + +import ( + "net/http/httptest" + "testing" + + nf_context "github.com/andy89923/nf-example/internal/context" + "github.com/andy89923/nf-example/internal/sbi/processor" + "github.com/gin-gonic/gin" + gomock "go.uber.org/mock/gomock" +) + +func Test_FindSpyFamilyCharacterName(t *testing.T) { + mockCtrl := gomock.NewController(t) + processorNf := processor.NewMockProcessorNf(mockCtrl) + processor, err := processor.NewProcessor(processorNf) + if err != nil { + t.Errorf("Failed to create processor: %s", err) + return + } + + t.Run("Find Character That Exists", func(t *testing.T) { + const INPUT_NAME = "Anya" + const EXPECTED_STATUS = 200 + const EXPECTED_BODY = "Character: " + INPUT_NAME + " Forger" + + processorNf.EXPECT().Context().Return(&nf_context.NFContext{ + SpyFamilyData: map[string]string{ + "Anya": "Forger", + }, + }) + + httpRecorder := httptest.NewRecorder() + ginCtx, _ := gin.CreateTestContext(httpRecorder) + processor.FindSpyFamilyCharacterName(ginCtx, INPUT_NAME) + + if httpRecorder.Code != EXPECTED_STATUS { + t.Errorf("Expected status code %d, got %d", EXPECTED_STATUS, httpRecorder.Code) + } + + if httpRecorder.Body.String() != EXPECTED_BODY { + t.Errorf("Expected body %s, got %s", EXPECTED_BODY, httpRecorder.Body.String()) + } + }) + + t.Run("Find Character That Does Not Exist", func(t *testing.T) { + const INPUT_NAME = "Andy" + const EXPECTED_STATUS = 404 + const EXPECTED_BODY = "[" + INPUT_NAME + "] not found in SPYxFAMILY" + + processorNf.EXPECT().Context().Return(&nf_context.NFContext{ + SpyFamilyData: map[string]string{ + "Anya": "Forger", + }, + }) + + httpRecorder := httptest.NewRecorder() + ginCtx, _ := gin.CreateTestContext(httpRecorder) + processor.FindSpyFamilyCharacterName(ginCtx, INPUT_NAME) + + if httpRecorder.Code != EXPECTED_STATUS { + t.Errorf("Expected status code %d, got %d", EXPECTED_STATUS, httpRecorder.Code) + } + + if httpRecorder.Body.String() != EXPECTED_BODY { + t.Errorf("Expected body %s, got %s", EXPECTED_BODY, httpRecorder.Body.String()) + } + }) +} diff --git a/internal/sbi/server_mock.go b/internal/sbi/server_mock.go new file mode 100644 index 0000000..7655763 --- /dev/null +++ b/internal/sbi/server_mock.go @@ -0,0 +1,144 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: internal/sbi/server.go +// +// Generated by this command: +// +// mockgen -source=internal/sbi/server.go -package sbi +// + +// Package sbi is a generated GoMock package. +package sbi + +import ( + reflect "reflect" + + context "github.com/andy89923/nf-example/internal/context" + processor "github.com/andy89923/nf-example/internal/sbi/processor" + factory "github.com/andy89923/nf-example/pkg/factory" + gomock "go.uber.org/mock/gomock" +) + +// MocknfApp is a mock of nfApp interface. +type MocknfApp struct { + ctrl *gomock.Controller + recorder *MocknfAppMockRecorder +} + +// MocknfAppMockRecorder is the mock recorder for MocknfApp. +type MocknfAppMockRecorder struct { + mock *MocknfApp +} + +// NewMocknfApp creates a new mock instance. +func NewMocknfApp(ctrl *gomock.Controller) *MocknfApp { + mock := &MocknfApp{ctrl: ctrl} + mock.recorder = &MocknfAppMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MocknfApp) EXPECT() *MocknfAppMockRecorder { + return m.recorder +} + +// Config mocks base method. +func (m *MocknfApp) Config() *factory.Config { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Config") + ret0, _ := ret[0].(*factory.Config) + return ret0 +} + +// Config indicates an expected call of Config. +func (mr *MocknfAppMockRecorder) Config() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Config", reflect.TypeOf((*MocknfApp)(nil).Config)) +} + +// Context mocks base method. +func (m *MocknfApp) Context() *context.NFContext { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Context") + ret0, _ := ret[0].(*context.NFContext) + return ret0 +} + +// Context indicates an expected call of Context. +func (mr *MocknfAppMockRecorder) Context() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Context", reflect.TypeOf((*MocknfApp)(nil).Context)) +} + +// Processor mocks base method. +func (m *MocknfApp) Processor() *processor.Processor { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Processor") + ret0, _ := ret[0].(*processor.Processor) + return ret0 +} + +// Processor indicates an expected call of Processor. +func (mr *MocknfAppMockRecorder) Processor() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Processor", reflect.TypeOf((*MocknfApp)(nil).Processor)) +} + +// SetLogEnable mocks base method. +func (m *MocknfApp) SetLogEnable(enable bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLogEnable", enable) +} + +// SetLogEnable indicates an expected call of SetLogEnable. +func (mr *MocknfAppMockRecorder) SetLogEnable(enable any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogEnable", reflect.TypeOf((*MocknfApp)(nil).SetLogEnable), enable) +} + +// SetLogLevel mocks base method. +func (m *MocknfApp) SetLogLevel(level string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetLogLevel", level) +} + +// SetLogLevel indicates an expected call of SetLogLevel. +func (mr *MocknfAppMockRecorder) SetLogLevel(level any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetLogLevel", reflect.TypeOf((*MocknfApp)(nil).SetLogLevel), level) +} + +// SetReportCaller mocks base method. +func (m *MocknfApp) SetReportCaller(reportCaller bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetReportCaller", reportCaller) +} + +// SetReportCaller indicates an expected call of SetReportCaller. +func (mr *MocknfAppMockRecorder) SetReportCaller(reportCaller any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetReportCaller", reflect.TypeOf((*MocknfApp)(nil).SetReportCaller), reportCaller) +} + +// Start mocks base method. +func (m *MocknfApp) Start() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Start") +} + +// Start indicates an expected call of Start. +func (mr *MocknfAppMockRecorder) Start() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MocknfApp)(nil).Start)) +} + +// Terminate mocks base method. +func (m *MocknfApp) Terminate() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Terminate") +} + +// Terminate indicates an expected call of Terminate. +func (mr *MocknfAppMockRecorder) Terminate() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Terminate", reflect.TypeOf((*MocknfApp)(nil).Terminate)) +}