From 7aa393656a8fb8f4eee2a43eb3000102154a0663 Mon Sep 17 00:00:00 2001 From: simady Date: Tue, 13 Aug 2019 22:05:22 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=E6=9C=80=E5=B0=8F=E9=99=90=E3=81=AE?= =?UTF-8?q?=E3=81=8A=E3=81=BF=E3=81=8F=E3=81=98=E6=A9=9F=E8=83=BD=E3=82=92?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai4/cmd/main.go | 9 ++ kadai4/go.mod | 3 + kadai4/pkg/api/api.go | 22 +++++ kadai4/pkg/api/app/handler/omikuji/handler.go | 25 ++++++ kadai4/pkg/api/app/middleware/context.go | 45 ++++++++++ .../pkg/api/domain/entity/omikuji/entity.go | 38 ++++++++ .../pkg/api/domain/service/omikuji/service.go | 89 +++++++++++++++++++ kadai4/pkg/api/error/error.go | 16 ++++ 8 files changed, 247 insertions(+) create mode 100644 kadai4/cmd/main.go create mode 100644 kadai4/go.mod create mode 100644 kadai4/pkg/api/api.go create mode 100644 kadai4/pkg/api/app/handler/omikuji/handler.go create mode 100644 kadai4/pkg/api/app/middleware/context.go create mode 100644 kadai4/pkg/api/domain/entity/omikuji/entity.go create mode 100644 kadai4/pkg/api/domain/service/omikuji/service.go create mode 100644 kadai4/pkg/api/error/error.go diff --git a/kadai4/cmd/main.go b/kadai4/cmd/main.go new file mode 100644 index 0000000..85e908e --- /dev/null +++ b/kadai4/cmd/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "omikuji-app/pkg/api" +) + +func main() { + api.Serve(":8081") +} diff --git a/kadai4/go.mod b/kadai4/go.mod new file mode 100644 index 0000000..17d4090 --- /dev/null +++ b/kadai4/go.mod @@ -0,0 +1,3 @@ +module omikuji-app + +go 1.12 diff --git a/kadai4/pkg/api/api.go b/kadai4/pkg/api/api.go new file mode 100644 index 0000000..0673a35 --- /dev/null +++ b/kadai4/pkg/api/api.go @@ -0,0 +1,22 @@ +package api + +import ( + "fmt" + "net/http" + "os" + + "omikuji-app/pkg/api/app/middleware" + + omikujiHandler "omikuji-app/pkg/api/app/handler/omikuji" + omikujiService "omikuji-app/pkg/api/domain/service/omikuji" +) + +func Serve(addr string) { + http.Handle("/", middleware.With(omikujiHandler.New(omikujiService.New()), middleware.ContextMiddleWare{}, middleware.ResponseHeaderMiddleWare{})) + http.Handle("/favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "Favicon is not set.", http.StatusNotFound) + })) + if err := http.ListenAndServe(addr, nil); err != nil { + fmt.Fprintf(os.Stderr, "Failed to serve. err = %v\n", err) + } +} diff --git a/kadai4/pkg/api/app/handler/omikuji/handler.go b/kadai4/pkg/api/app/handler/omikuji/handler.go new file mode 100644 index 0000000..76a5d26 --- /dev/null +++ b/kadai4/pkg/api/app/handler/omikuji/handler.go @@ -0,0 +1,25 @@ +package omikuji + +import ( + "fmt" + "net/http" + "os" + + service "omikuji-app/pkg/api/domain/service/omikuji" +) + +type omikujiHandler struct { + omikujiService service.OmikujiService +} + +func New(s service.OmikujiService) http.Handler { + return &omikujiHandler{omikujiService: s} +} + +func (h *omikujiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + res, err := h.omikujiService.Draw() + if err != nil { + fmt.Fprintf(os.Stderr, "抽選に失敗しました. err = %v\n", err) + } + fmt.Fprintf(w, "%s", res) +} diff --git a/kadai4/pkg/api/app/middleware/context.go b/kadai4/pkg/api/app/middleware/context.go new file mode 100644 index 0000000..eef3aad --- /dev/null +++ b/kadai4/pkg/api/app/middleware/context.go @@ -0,0 +1,45 @@ +package middleware + +import ( + "context" + "net/http" + "time" +) + +type MiddleWare interface { + ServeNext(h http.Handler) http.Handler +} + +type MiddleWareFunc func(h http.Handler) http.Handler + +func (f MiddleWareFunc) ServeNext(h http.Handler) http.Handler { + return f(h) +} + +func With(h http.Handler, ms ...MiddleWare) http.Handler { + for _, m := range ms { + h = m.ServeNext(h) + } + return h +} + +type ContextMiddleWare struct{} + +func (m ContextMiddleWare) ServeNext(h http.Handler) http.Handler { + f := func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(context.Background(), "time", time.Now()) + r.WithContext(ctx) + h.ServeHTTP(w, r) + } + return http.HandlerFunc(f) +} + +type ResponseHeaderMiddleWare struct{} + +func (m ResponseHeaderMiddleWare) ServeNext(h http.Handler) http.Handler { + f := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + h.ServeHTTP(w, r) + } + return http.HandlerFunc(f) +} diff --git a/kadai4/pkg/api/domain/entity/omikuji/entity.go b/kadai4/pkg/api/domain/entity/omikuji/entity.go new file mode 100644 index 0000000..abbc8f8 --- /dev/null +++ b/kadai4/pkg/api/domain/entity/omikuji/entity.go @@ -0,0 +1,38 @@ +package omikuji + +import ( + "log" + "math/rand" + "time" +) + +// おみくじ結果 +type OmikujiResult struct { + ID int32 `json:"id"` + Ruck string `json:"ruck"` + Message string `json:"message"` +} + +func init() { + rand.Seed(time.Now().UnixNano()) + log.Println("Seed initialized...") +} + +// おみくじ結果セット +type OmikujiResults []OmikujiResult + +// FindRandom おみくじ結果セットからランダムに一つを取得する. +func (rs OmikujiResults) FindRandom() OmikujiResult { + return rs[rand.Int31n(int32(len(rs)))] +} + +// ExtractByRuck おみくじ結果セットから特定のruckを抽出する. +func (rs OmikujiResults) ExtractByRuck(ruck string) OmikujiResults { + var ret OmikujiResults + for _, r := range rs { + if r.Ruck == ruck { + ret = append(ret, r) + } + } + return ret +} diff --git a/kadai4/pkg/api/domain/service/omikuji/service.go b/kadai4/pkg/api/domain/service/omikuji/service.go new file mode 100644 index 0000000..feda805 --- /dev/null +++ b/kadai4/pkg/api/domain/service/omikuji/service.go @@ -0,0 +1,89 @@ +package omikuji + +import ( + "bytes" + "encoding/json" + "time" + + entity "omikuji-app/pkg/api/domain/entity/omikuji" +) + +var rs = entity.OmikujiResults{ + { + ID: 1, + Ruck: "大吉", + Message: "おめでとうございます!大吉です!", + }, + { + ID: 2, + Ruck: "大吉", + Message: "大吉でした!絶好調です!", + }, + { + ID: 3, + Ruck: "吉", + Message: "吉です!かなりツイてます!", + }, + { + ID: 4, + Ruck: "吉", + Message: "吉です!良い運勢ですね!", + }, + { + ID: 5, + Ruck: "中吉", + Message: "中吉でした!いい感じです!", + }, + { + ID: 6, + Ruck: "中吉", + Message: "なかなかいいですね!中吉です!", + }, + { + ID: 7, + Ruck: "小吉", + Message: "小吉です!悪くないですね!", + }, + { + ID: 8, + Ruck: "小吉", + Message: "小吉です!少しツイてます!", + }, + { + ID: 9, + Ruck: "小吉", + Message: "小吉でした!!!", + }, + { + ID: 10, + Ruck: "凶", + Message: "凶でした!今日も一日頑張りましょう!", + }, +} + +type OmikujiService interface { + Draw() (string, error) +} + +type omikujiService struct { +} + +func New() OmikujiService { + return &omikujiService{} +} + +// Draw おみくじを引く. +func (s *omikujiService) Draw() (string, error) { + t := time.Now() + day := t.Format("1/2") + if day == "1/1" || day == "1/2" || day == "1/3" { + rs = rs.ExtractByRuck("大吉") + } + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + if err := enc.Encode(rs.FindRandom()); err != nil { + // JSONエンコードに失敗しました + return "", err + } + return buf.String(), nil +} diff --git a/kadai4/pkg/api/error/error.go b/kadai4/pkg/api/error/error.go new file mode 100644 index 0000000..22439c2 --- /dev/null +++ b/kadai4/pkg/api/error/error.go @@ -0,0 +1,16 @@ +package error + +import "fmt" + +type ApiError struct { + message string + code string +} + +func New(m, c string) error { + return &ApiError{message: m, code: c} +} + +func (e *ApiError) Error() string { + return fmt.Sprintf("Error has occurred! message = %v, code = %v", e.message, e.code) +} From 73afe9cc2afd8ea1b6263d5a64c9cbff57ae2113 Mon Sep 17 00:00:00 2001 From: simady Date: Wed, 14 Aug 2019 00:53:30 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=81=AE?= =?UTF-8?q?=E8=A8=98=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai4/pkg/api/app/handler/omikuji/handler.go | 13 +- .../api/app/handler/omikuji/handler_test.go | 92 ++++++++++++ kadai4/pkg/api/app/middleware/context.go | 8 +- .../api/domain/entity/omikuji/entity_test.go | 135 ++++++++++++++++++ .../service/omikuji/mock/service_mock.go | 26 ++++ .../pkg/api/domain/service/omikuji/service.go | 20 +-- .../domain/service/omikuji/service_test.go | 57 ++++++++ kadai4/pkg/api/error/error.go | 16 --- kadai4/pkg/api/ocontext/context.go | 18 +++ kadai4/pkg/api/ocontext/context_test.go | 62 ++++++++ 10 files changed, 413 insertions(+), 34 deletions(-) create mode 100644 kadai4/pkg/api/app/handler/omikuji/handler_test.go create mode 100644 kadai4/pkg/api/domain/entity/omikuji/entity_test.go create mode 100644 kadai4/pkg/api/domain/service/omikuji/mock/service_mock.go create mode 100644 kadai4/pkg/api/domain/service/omikuji/service_test.go delete mode 100644 kadai4/pkg/api/error/error.go create mode 100644 kadai4/pkg/api/ocontext/context.go create mode 100644 kadai4/pkg/api/ocontext/context_test.go diff --git a/kadai4/pkg/api/app/handler/omikuji/handler.go b/kadai4/pkg/api/app/handler/omikuji/handler.go index 76a5d26..cfaa87f 100644 --- a/kadai4/pkg/api/app/handler/omikuji/handler.go +++ b/kadai4/pkg/api/app/handler/omikuji/handler.go @@ -1,6 +1,8 @@ package omikuji import ( + "bytes" + "encoding/json" "fmt" "net/http" "os" @@ -17,9 +19,14 @@ func New(s service.OmikujiService) http.Handler { } func (h *omikujiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - res, err := h.omikujiService.Draw() - if err != nil { + ctx := r.Context() + rs := h.omikujiService.Draw(ctx) + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + if err := enc.Encode(rs); err != nil { fmt.Fprintf(os.Stderr, "抽選に失敗しました. err = %v\n", err) + http.Error(w, "抽選に失敗しました.", http.StatusInternalServerError) + return } - fmt.Fprintf(w, "%s", res) + fmt.Fprintf(w, "%s", buf.String()) } diff --git a/kadai4/pkg/api/app/handler/omikuji/handler_test.go b/kadai4/pkg/api/app/handler/omikuji/handler_test.go new file mode 100644 index 0000000..5e00475 --- /dev/null +++ b/kadai4/pkg/api/app/handler/omikuji/handler_test.go @@ -0,0 +1,92 @@ +package omikuji + +import ( + "context" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "testing" + "time" + + "omikuji-app/pkg/api/ocontext" + + service "omikuji-app/pkg/api/domain/service/omikuji" + mockService "omikuji-app/pkg/api/domain/service/omikuji/mock" +) + +func TestNew(t *testing.T) { + type args struct { + s service.OmikujiService + } + tests := []struct { + name string + args args + want http.Handler + }{ + { + name: "omikujiHandlerの生成", + args: args{ + s: mockService.New(), + }, + want: &omikujiHandler{omikujiService: mockService.New()}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := New(tt.args.s); !reflect.DeepEqual(got, tt.want) { + t.Errorf("New() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_omikujiHandler_ServeHTTP(t *testing.T) { + type fields struct { + omikujiService service.OmikujiService + } + type args struct { + w http.ResponseWriter + r *http.Request + } + tests := []struct { + name string + fields fields + args args + want string + wantCode int + }{ + { + name: "リクエスト成功", + fields: fields{ + omikujiService: mockService.New(), + }, + args: args{ + w: httptest.NewRecorder(), + r: httptest.NewRequest("GET", "/", nil).WithContext(ocontext.SetAccessTime(context.Background(), time.Now())), + }, + want: "{\"id\":4,\"ruck\":\"吉\",\"message\":\"吉です!良い運勢ですね!\"}\n", + wantCode: http.StatusOK, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := &omikujiHandler{ + omikujiService: tt.fields.omikujiService, + } + h.ServeHTTP(tt.args.w, tt.args.r) + rw := tt.args.w.(*httptest.ResponseRecorder).Result() + defer rw.Body.Close() + if rw.StatusCode != tt.wantCode { + t.Errorf("unexpected status code: %v, want %v", rw.StatusCode, tt.wantCode) + } + b, err := ioutil.ReadAll(rw.Body) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if s := string(b); s != tt.want { + t.Errorf("unexpected response: %v, want %v", s, tt.want) + } + }) + } +} diff --git a/kadai4/pkg/api/app/middleware/context.go b/kadai4/pkg/api/app/middleware/context.go index eef3aad..706bc05 100644 --- a/kadai4/pkg/api/app/middleware/context.go +++ b/kadai4/pkg/api/app/middleware/context.go @@ -4,6 +4,8 @@ import ( "context" "net/http" "time" + + "omikuji-app/pkg/api/ocontext" ) type MiddleWare interface { @@ -23,17 +25,19 @@ func With(h http.Handler, ms ...MiddleWare) http.Handler { return h } +// ContextMiddleWare リクエスト起因のデータを格納する. type ContextMiddleWare struct{} func (m ContextMiddleWare) ServeNext(h http.Handler) http.Handler { f := func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithValue(context.Background(), "time", time.Now()) - r.WithContext(ctx) + ctx := ocontext.SetAccessTime(context.Background(), time.Now()) + r = r.WithContext(ctx) h.ServeHTTP(w, r) } return http.HandlerFunc(f) } +// ResponseHeaderMiddleWare レスポンスヘッダーを設定する. type ResponseHeaderMiddleWare struct{} func (m ResponseHeaderMiddleWare) ServeNext(h http.Handler) http.Handler { diff --git a/kadai4/pkg/api/domain/entity/omikuji/entity_test.go b/kadai4/pkg/api/domain/entity/omikuji/entity_test.go new file mode 100644 index 0000000..1b44d9c --- /dev/null +++ b/kadai4/pkg/api/domain/entity/omikuji/entity_test.go @@ -0,0 +1,135 @@ +package omikuji + +import ( + "reflect" + "testing" +) + +func TestOmikujiResults_FindRandom(t *testing.T) { + tests := []struct { + name string + rs OmikujiResults + }{ + { + name: "ランダム選択", + rs: OmikujiResults{ + { + ID: 1, + Ruck: "大吉", + Message: "メッセージ1", + }, + { + ID: 2, + Ruck: "吉", + Message: "メッセージ2", + }, + { + ID: 3, + Ruck: "中吉", + Message: "メッセージ3", + }, + { + ID: 4, + Ruck: "小吉", + Message: "メッセージ4", + }, + { + ID: 5, + Ruck: "凶", + Message: "メッセージ5", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := tt.rs.FindRandom() + // ランダム値で正否を判断できないのでログだけ出力 + t.Log(res) + }) + } +} + +func TestOmikujiResults_ExtractByRuck(t *testing.T) { + type args struct { + ruck string + } + tests := []struct { + name string + rs OmikujiResults + args args + want OmikujiResults + }{ + { + name: "小吉を抽出", + rs: OmikujiResults{ + { + ID: 1, + Ruck: "大吉", + Message: "メッセージ1", + }, + { + ID: 2, + Ruck: "吉", + Message: "メッセージ2", + }, + { + ID: 3, + Ruck: "小吉", + Message: "メッセージ3", + }, + { + ID: 4, + Ruck: "小吉", + Message: "メッセージ4", + }, + { + ID: 5, + Ruck: "凶", + Message: "メッセージ5", + }, + }, + args: args{ + ruck: "小吉", + }, + want: OmikujiResults{ + { + ID: 3, + Ruck: "小吉", + Message: "メッセージ3", + }, + { + ID: 4, + Ruck: "小吉", + Message: "メッセージ4", + }, + }, + }, + { + name: "一致するものがない", + rs: OmikujiResults{ + { + ID: 1, + Ruck: "大吉", + Message: "メッセージ1", + }, + { + ID: 2, + Ruck: "吉", + Message: "メッセージ2", + }, + }, + args: args{ + ruck: "凶", + }, + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.rs.ExtractByRuck(tt.args.ruck); !reflect.DeepEqual(got, tt.want) { + t.Errorf("OmikujiResults.ExtractByRuck() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/kadai4/pkg/api/domain/service/omikuji/mock/service_mock.go b/kadai4/pkg/api/domain/service/omikuji/mock/service_mock.go new file mode 100644 index 0000000..a4bed51 --- /dev/null +++ b/kadai4/pkg/api/domain/service/omikuji/mock/service_mock.go @@ -0,0 +1,26 @@ +package mock + +import ( + "context" + + entity "omikuji-app/pkg/api/domain/entity/omikuji" + "omikuji-app/pkg/api/domain/service/omikuji" +) + +// mockService OmikujiServiceのモック. +type mockService struct { +} + +// New モックを生成する. +func New() omikuji.OmikujiService { + return &mockService{} +} + +// Draw おみくじを引く. +func (s *mockService) Draw(ctx context.Context) entity.OmikujiResult { + return entity.OmikujiResult{ + ID: 4, + Ruck: "吉", + Message: "吉です!良い運勢ですね!", + } +} diff --git a/kadai4/pkg/api/domain/service/omikuji/service.go b/kadai4/pkg/api/domain/service/omikuji/service.go index feda805..1112cc7 100644 --- a/kadai4/pkg/api/domain/service/omikuji/service.go +++ b/kadai4/pkg/api/domain/service/omikuji/service.go @@ -1,9 +1,9 @@ package omikuji import ( - "bytes" - "encoding/json" - "time" + "context" + + "omikuji-app/pkg/api/ocontext" entity "omikuji-app/pkg/api/domain/entity/omikuji" ) @@ -62,7 +62,7 @@ var rs = entity.OmikujiResults{ } type OmikujiService interface { - Draw() (string, error) + Draw(ctx context.Context) entity.OmikujiResult } type omikujiService struct { @@ -73,17 +73,11 @@ func New() OmikujiService { } // Draw おみくじを引く. -func (s *omikujiService) Draw() (string, error) { - t := time.Now() +func (s *omikujiService) Draw(ctx context.Context) entity.OmikujiResult { + t := ocontext.GetAccessTime(ctx) day := t.Format("1/2") if day == "1/1" || day == "1/2" || day == "1/3" { rs = rs.ExtractByRuck("大吉") } - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - if err := enc.Encode(rs.FindRandom()); err != nil { - // JSONエンコードに失敗しました - return "", err - } - return buf.String(), nil + return rs.FindRandom() } diff --git a/kadai4/pkg/api/domain/service/omikuji/service_test.go b/kadai4/pkg/api/domain/service/omikuji/service_test.go new file mode 100644 index 0000000..361f77d --- /dev/null +++ b/kadai4/pkg/api/domain/service/omikuji/service_test.go @@ -0,0 +1,57 @@ +package omikuji + +import ( + "context" + "reflect" + "testing" + "time" + + "omikuji-app/pkg/api/ocontext" +) + +func TestNew(t *testing.T) { + tests := []struct { + name string + want OmikujiService + }{ + { + name: "omikujiServiceの生成", + want: &omikujiService{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := New(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("New() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_omikujiService_Draw(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + s *omikujiService + args args + want string + }{ + { + name: "1/2のおみくじ", + s: &omikujiService{}, + args: args{ + ctx: ocontext.SetAccessTime(context.Background(), time.Date(2000, 1, 2, 3, 4, 5, 6, time.Local)), + }, + want: "大吉", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.s.Draw(tt.args.ctx); !reflect.DeepEqual(got.Ruck, tt.want) { + t.Errorf("omikujiService.Draw() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/kadai4/pkg/api/error/error.go b/kadai4/pkg/api/error/error.go deleted file mode 100644 index 22439c2..0000000 --- a/kadai4/pkg/api/error/error.go +++ /dev/null @@ -1,16 +0,0 @@ -package error - -import "fmt" - -type ApiError struct { - message string - code string -} - -func New(m, c string) error { - return &ApiError{message: m, code: c} -} - -func (e *ApiError) Error() string { - return fmt.Sprintf("Error has occurred! message = %v, code = %v", e.message, e.code) -} diff --git a/kadai4/pkg/api/ocontext/context.go b/kadai4/pkg/api/ocontext/context.go new file mode 100644 index 0000000..5a78e92 --- /dev/null +++ b/kadai4/pkg/api/ocontext/context.go @@ -0,0 +1,18 @@ +package ocontext + +import ( + "context" + "time" +) + +type accessTimeKey struct{} + +// SetAccessTime contextにアクセス日時を設定する. +func SetAccessTime(ctx context.Context, time time.Time) context.Context { + return context.WithValue(ctx, accessTimeKey{}, time) +} + +// GetAccessTime contextからアクセス日時を取得する. +func GetAccessTime(ctx context.Context) time.Time { + return ctx.Value(accessTimeKey{}).(time.Time) +} diff --git a/kadai4/pkg/api/ocontext/context_test.go b/kadai4/pkg/api/ocontext/context_test.go new file mode 100644 index 0000000..324b70d --- /dev/null +++ b/kadai4/pkg/api/ocontext/context_test.go @@ -0,0 +1,62 @@ +package ocontext + +import ( + "context" + "reflect" + "testing" + "time" +) + +func TestSetAccessTime(t *testing.T) { + type args struct { + ctx context.Context + time time.Time + } + tests := []struct { + name string + args args + want context.Context + }{ + { + name: "アクセス時刻の設定", + args: args{ + ctx: context.Background(), + time: time.Date(2000, 1, 2, 3, 4, 5, 6, time.Local), + }, + want: context.WithValue(context.Background(), accessTimeKey{}, time.Date(2000, 1, 2, 3, 4, 5, 6, time.Local)), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := SetAccessTime(tt.args.ctx, tt.args.time); !reflect.DeepEqual(got, tt.want) { + t.Errorf("SetAccessTime() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetAccessTime(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want time.Time + }{ + { + name: "アクセス時刻の取得", + args: args{ + ctx: context.WithValue(context.Background(), accessTimeKey{}, time.Date(2000, 1, 2, 3, 4, 5, 6, time.Local)), + }, + want: time.Date(2000, 1, 2, 3, 4, 5, 6, time.Local), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetAccessTime(tt.args.ctx); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAccessTime() = %v, want %v", got, tt.want) + } + }) + } +} From ac25666fe30ad28c1d0fb27778d3881f1e60e26f Mon Sep 17 00:00:00 2001 From: simady Date: Wed, 14 Aug 2019 19:19:42 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=E3=82=A2=E3=83=BC=E3=82=AD=E3=83=86?= =?UTF-8?q?=E3=82=AF=E3=83=81=E3=83=A3=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai4/pkg/api/api.go | 12 +- kadai4/pkg/api/app/handler/omikuji/handler.go | 19 ++-- .../api/app/handler/omikuji/handler_test.go | 31 ++++-- .../api/app/interactor/omikuji/interactor.go | 30 +++++ .../app/interactor/omikuji/interactor_test.go | 104 ++++++++++++++++++ .../omikuji/mock/interactor_mock.go | 35 ++++++ .../middleware/{context.go => middleware.go} | 6 - .../pkg/api/app/middleware/middleware_test.go | 87 +++++++++++++++ .../api/app/presenter/mock/presenter_mock.go | 35 ++++++ kadai4/pkg/api/app/presenter/presenter.go | 26 +++++ .../pkg/api/app/presenter/presenter_test.go | 67 +++++++++++ kadai4/pkg/api/domain/service/omikuji/data.go | 56 ++++++++++ .../pkg/api/domain/service/omikuji/service.go | 63 ++--------- .../domain/service/omikuji/service_test.go | 10 +- 14 files changed, 493 insertions(+), 88 deletions(-) create mode 100644 kadai4/pkg/api/app/interactor/omikuji/interactor.go create mode 100644 kadai4/pkg/api/app/interactor/omikuji/interactor_test.go create mode 100644 kadai4/pkg/api/app/interactor/omikuji/mock/interactor_mock.go rename kadai4/pkg/api/app/middleware/{context.go => middleware.go} (88%) create mode 100644 kadai4/pkg/api/app/middleware/middleware_test.go create mode 100644 kadai4/pkg/api/app/presenter/mock/presenter_mock.go create mode 100644 kadai4/pkg/api/app/presenter/presenter.go create mode 100644 kadai4/pkg/api/app/presenter/presenter_test.go create mode 100644 kadai4/pkg/api/domain/service/omikuji/data.go diff --git a/kadai4/pkg/api/api.go b/kadai4/pkg/api/api.go index 0673a35..f6b78c0 100644 --- a/kadai4/pkg/api/api.go +++ b/kadai4/pkg/api/api.go @@ -3,16 +3,22 @@ package api import ( "fmt" "net/http" - "os" - "omikuji-app/pkg/api/app/middleware" + "os" omikujiHandler "omikuji-app/pkg/api/app/handler/omikuji" + omikujiInteractor "omikuji-app/pkg/api/app/interactor/omikuji" + "omikuji-app/pkg/api/app/middleware" + "omikuji-app/pkg/api/app/presenter" omikujiService "omikuji-app/pkg/api/domain/service/omikuji" ) func Serve(addr string) { - http.Handle("/", middleware.With(omikujiHandler.New(omikujiService.New()), middleware.ContextMiddleWare{}, middleware.ResponseHeaderMiddleWare{})) + jsonPresenter := presenter.New() + service := omikujiService.New() + interactor := omikujiInteractor.New(jsonPresenter, service) + handler := omikujiHandler.New(interactor) + http.Handle("/", middleware.With(handler, middleware.ContextMiddleWare{}, middleware.ResponseHeaderMiddleWare{})) http.Handle("/favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Favicon is not set.", http.StatusNotFound) })) diff --git a/kadai4/pkg/api/app/handler/omikuji/handler.go b/kadai4/pkg/api/app/handler/omikuji/handler.go index cfaa87f..9cd9a47 100644 --- a/kadai4/pkg/api/app/handler/omikuji/handler.go +++ b/kadai4/pkg/api/app/handler/omikuji/handler.go @@ -1,32 +1,27 @@ package omikuji import ( - "bytes" - "encoding/json" "fmt" "net/http" "os" - service "omikuji-app/pkg/api/domain/service/omikuji" + interactor "omikuji-app/pkg/api/app/interactor/omikuji" ) type omikujiHandler struct { - omikujiService service.OmikujiService + omikujiInteractor interactor.OmikujiInteractor } -func New(s service.OmikujiService) http.Handler { - return &omikujiHandler{omikujiService: s} +func New(i interactor.OmikujiInteractor) http.Handler { + return &omikujiHandler{omikujiInteractor: i} } func (h *omikujiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - rs := h.omikujiService.Draw(ctx) - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - if err := enc.Encode(rs); err != nil { + res, err := h.omikujiInteractor.Draw(r.Context()) + if err != nil { fmt.Fprintf(os.Stderr, "抽選に失敗しました. err = %v\n", err) http.Error(w, "抽選に失敗しました.", http.StatusInternalServerError) return } - fmt.Fprintf(w, "%s", buf.String()) + fmt.Fprintf(w, "%s", res) } diff --git a/kadai4/pkg/api/app/handler/omikuji/handler_test.go b/kadai4/pkg/api/app/handler/omikuji/handler_test.go index 5e00475..608b0af 100644 --- a/kadai4/pkg/api/app/handler/omikuji/handler_test.go +++ b/kadai4/pkg/api/app/handler/omikuji/handler_test.go @@ -9,15 +9,14 @@ import ( "testing" "time" + interactor "omikuji-app/pkg/api/app/interactor/omikuji" + mockInteractor "omikuji-app/pkg/api/app/interactor/omikuji/mock" "omikuji-app/pkg/api/ocontext" - - service "omikuji-app/pkg/api/domain/service/omikuji" - mockService "omikuji-app/pkg/api/domain/service/omikuji/mock" ) func TestNew(t *testing.T) { type args struct { - s service.OmikujiService + i interactor.OmikujiInteractor } tests := []struct { name string @@ -27,14 +26,14 @@ func TestNew(t *testing.T) { { name: "omikujiHandlerの生成", args: args{ - s: mockService.New(), + i: mockInteractor.New(), }, - want: &omikujiHandler{omikujiService: mockService.New()}, + want: &omikujiHandler{omikujiInteractor: mockInteractor.New()}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := New(tt.args.s); !reflect.DeepEqual(got, tt.want) { + if got := New(tt.args.i); !reflect.DeepEqual(got, tt.want) { t.Errorf("New() = %v, want %v", got, tt.want) } }) @@ -43,7 +42,7 @@ func TestNew(t *testing.T) { func Test_omikujiHandler_ServeHTTP(t *testing.T) { type fields struct { - omikujiService service.OmikujiService + omikujiInteractor interactor.OmikujiInteractor } type args struct { w http.ResponseWriter @@ -59,7 +58,7 @@ func Test_omikujiHandler_ServeHTTP(t *testing.T) { { name: "リクエスト成功", fields: fields{ - omikujiService: mockService.New(), + omikujiInteractor: mockInteractor.New(), }, args: args{ w: httptest.NewRecorder(), @@ -68,11 +67,23 @@ func Test_omikujiHandler_ServeHTTP(t *testing.T) { want: "{\"id\":4,\"ruck\":\"吉\",\"message\":\"吉です!良い運勢ですね!\"}\n", wantCode: http.StatusOK, }, + { + name: "リクエスト失敗", + fields: fields{ + omikujiInteractor: mockInteractor.NewError(), + }, + args: args{ + w: httptest.NewRecorder(), + r: httptest.NewRequest("GET", "/", nil).WithContext(ocontext.SetAccessTime(context.Background(), time.Now())), + }, + want: "抽選に失敗しました.\n", + wantCode: http.StatusInternalServerError, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { h := &omikujiHandler{ - omikujiService: tt.fields.omikujiService, + omikujiInteractor: tt.fields.omikujiInteractor, } h.ServeHTTP(tt.args.w, tt.args.r) rw := tt.args.w.(*httptest.ResponseRecorder).Result() diff --git a/kadai4/pkg/api/app/interactor/omikuji/interactor.go b/kadai4/pkg/api/app/interactor/omikuji/interactor.go new file mode 100644 index 0000000..1068dc4 --- /dev/null +++ b/kadai4/pkg/api/app/interactor/omikuji/interactor.go @@ -0,0 +1,30 @@ +package interactor + +import ( + "context" + + "omikuji-app/pkg/api/app/presenter" + service "omikuji-app/pkg/api/domain/service/omikuji" +) + +type OmikujiInteractor interface { + Draw(ctx context.Context) (string, error) +} + +type omikujiInteractor struct { + presenter presenter.Presenter + omikujiService service.OmikujiService +} + +func New(p presenter.Presenter, s service.OmikujiService) OmikujiInteractor { + return &omikujiInteractor{presenter: p, omikujiService: s} +} + +func (i *omikujiInteractor) Draw(ctx context.Context) (string, error) { + rs := i.omikujiService.Draw(ctx) + output, err := i.presenter.Output(rs) + if err != nil { + return "", err + } + return output, nil +} diff --git a/kadai4/pkg/api/app/interactor/omikuji/interactor_test.go b/kadai4/pkg/api/app/interactor/omikuji/interactor_test.go new file mode 100644 index 0000000..846e35a --- /dev/null +++ b/kadai4/pkg/api/app/interactor/omikuji/interactor_test.go @@ -0,0 +1,104 @@ +package interactor + +import ( + "context" + "fmt" + "reflect" + "testing" + + "omikuji-app/pkg/api/app/presenter" + mockPresenter "omikuji-app/pkg/api/app/presenter/mock" + entity "omikuji-app/pkg/api/domain/entity/omikuji" + service "omikuji-app/pkg/api/domain/service/omikuji" + mockService "omikuji-app/pkg/api/domain/service/omikuji/mock" +) + +func TestNew(t *testing.T) { + type args struct { + p presenter.Presenter + s service.OmikujiService + } + tests := []struct { + name string + args args + want OmikujiInteractor + }{ + { + name: "omikujiInteractorの生成", + args: args{ + p: mockPresenter.New(), + s: mockService.New(), + }, + want: &omikujiInteractor{presenter: mockPresenter.New(), omikujiService: mockService.New()}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := New(tt.args.p, tt.args.s); !reflect.DeepEqual(got, tt.want) { + t.Errorf("New() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_omikujiInteractor_Draw(t *testing.T) { + type fields struct { + presenter presenter.Presenter + omikujiService service.OmikujiService + } + type args struct { + ctx context.Context + } + tests := []struct { + name string + fields fields + args args + want string + wantErr bool + }{ + { + name: "正常終了", + fields: fields{ + presenter: mockPresenter.New(), + omikujiService: mockService.New(), + }, + args: args{ + ctx: context.Background(), + }, + want: fmt.Sprintf("output: %v", entity.OmikujiResult{ + ID: 4, + Ruck: "吉", + Message: "吉です!良い運勢ですね!", + }), + wantErr: false, + }, + { + name: "エラー発生", + fields: fields{ + presenter: mockPresenter.NewError(), + omikujiService: mockService.New(), + }, + args: args{ + ctx: context.Background(), + }, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + i := &omikujiInteractor{ + presenter: tt.fields.presenter, + omikujiService: tt.fields.omikujiService, + } + got, err := i.Draw(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("omikujiInteractor.Draw() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("omikujiInteractor.Draw() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/kadai4/pkg/api/app/interactor/omikuji/mock/interactor_mock.go b/kadai4/pkg/api/app/interactor/omikuji/mock/interactor_mock.go new file mode 100644 index 0000000..123eb88 --- /dev/null +++ b/kadai4/pkg/api/app/interactor/omikuji/mock/interactor_mock.go @@ -0,0 +1,35 @@ +package mock + +import ( + "context" + + interactor "omikuji-app/pkg/api/app/interactor/omikuji" +) + +type mockInteractor struct { +} + +func New() interactor.OmikujiInteractor { + return &mockInteractor{} +} + +func (i *mockInteractor) Draw(ctx context.Context) (string, error) { + return "{\"id\":4,\"ruck\":\"吉\",\"message\":\"吉です!良い運勢ですね!\"}\n", nil +} + +type mockErrorInteractor struct { +} + +func NewError() interactor.OmikujiInteractor { + return &mockErrorInteractor{} +} + +func (i *mockErrorInteractor) Draw(ctx context.Context) (string, error) { + return "", &MockError{} +} + +type MockError struct{} + +func (e *MockError) Error() string { + return "mock interactor error." +} diff --git a/kadai4/pkg/api/app/middleware/context.go b/kadai4/pkg/api/app/middleware/middleware.go similarity index 88% rename from kadai4/pkg/api/app/middleware/context.go rename to kadai4/pkg/api/app/middleware/middleware.go index 706bc05..2cd0878 100644 --- a/kadai4/pkg/api/app/middleware/context.go +++ b/kadai4/pkg/api/app/middleware/middleware.go @@ -12,12 +12,6 @@ type MiddleWare interface { ServeNext(h http.Handler) http.Handler } -type MiddleWareFunc func(h http.Handler) http.Handler - -func (f MiddleWareFunc) ServeNext(h http.Handler) http.Handler { - return f(h) -} - func With(h http.Handler, ms ...MiddleWare) http.Handler { for _, m := range ms { h = m.ServeNext(h) diff --git a/kadai4/pkg/api/app/middleware/middleware_test.go b/kadai4/pkg/api/app/middleware/middleware_test.go new file mode 100644 index 0000000..9e1304c --- /dev/null +++ b/kadai4/pkg/api/app/middleware/middleware_test.go @@ -0,0 +1,87 @@ +package middleware + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + "time" + + "omikuji-app/pkg/api/ocontext" +) + +func TestContextMiddleWare_ServeNext(t *testing.T) { + type args struct { + h http.Handler + } + tests := []struct { + name string + m ContextMiddleWare + args args + want string + }{ + { + name: "リクエスト起因データの設定", + m: ContextMiddleWare{}, + args: args{ + h: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Contextにセットされたアクセス時刻をレスポンスに書き込む + fmt.Fprintf(w, "%s", ocontext.GetAccessTime(r.Context()).Format("2006-01-02 15:04:05")) + }), + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.m.ServeNext(tt.args.h) + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + got.ServeHTTP(w, r) + + rw := w.Result() + defer rw.Body.Close() + b, err := ioutil.ReadAll(rw.Body) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + // 時刻としてパースできればOKとする + if _, err := time.Parse("2006-01-02 15:04:05", string(b)); err != nil { + t.Errorf("parse error: %v", err) + } + }) + } +} + +func TestResponseHeaderMiddleWare_ServeNext(t *testing.T) { + type args struct { + h http.Handler + } + tests := []struct { + name string + m ResponseHeaderMiddleWare + args args + want string + }{ + { + name: "Content-Typeの設定", + m: ResponseHeaderMiddleWare{}, + args: args{ + h: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}), + }, + want: "application/json; charset=utf-8", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := tt.m.ServeNext(tt.args.h) + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "/", nil) + got.ServeHTTP(w, r) + if c := w.Header().Get("Content-Type"); c != tt.want { + t.Errorf("Content-Type = %v, want %v", c, tt.want) + } + + }) + } +} diff --git a/kadai4/pkg/api/app/presenter/mock/presenter_mock.go b/kadai4/pkg/api/app/presenter/mock/presenter_mock.go new file mode 100644 index 0000000..eff8b73 --- /dev/null +++ b/kadai4/pkg/api/app/presenter/mock/presenter_mock.go @@ -0,0 +1,35 @@ +package mock + +import ( + "fmt" + + "omikuji-app/pkg/api/app/presenter" +) + +type mockPresenter struct { +} + +func New() presenter.Presenter { + return &mockPresenter{} +} + +func (p *mockPresenter) Output(v interface{}) (string, error) { + return fmt.Sprintf("output: %v", v), nil +} + +type mockErrorPresenter struct { +} + +func NewError() presenter.Presenter { + return &mockErrorPresenter{} +} + +func (p *mockErrorPresenter) Output(v interface{}) (string, error) { + return "", &MockError{} +} + +type MockError struct{} + +func (e *MockError) Error() string { + return "mock presenter error." +} diff --git a/kadai4/pkg/api/app/presenter/presenter.go b/kadai4/pkg/api/app/presenter/presenter.go new file mode 100644 index 0000000..87d7aaa --- /dev/null +++ b/kadai4/pkg/api/app/presenter/presenter.go @@ -0,0 +1,26 @@ +package presenter + +import ( + "bytes" + "encoding/json" +) + +type Presenter interface { + Output(v interface{}) (string, error) +} + +type presenter struct { +} + +func New() Presenter { + return &presenter{} +} + +func (p *presenter) Output(v interface{}) (string, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + if err := enc.Encode(v); err != nil { + return "", err + } + return buf.String(), nil +} diff --git a/kadai4/pkg/api/app/presenter/presenter_test.go b/kadai4/pkg/api/app/presenter/presenter_test.go new file mode 100644 index 0000000..505f591 --- /dev/null +++ b/kadai4/pkg/api/app/presenter/presenter_test.go @@ -0,0 +1,67 @@ +package presenter + +import ( + "reflect" + "testing" + + entity "omikuji-app/pkg/api/domain/entity/omikuji" +) + +func TestNew(t *testing.T) { + tests := []struct { + name string + want Presenter + }{ + { + name: "presenterの生成", + want: &presenter{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := New(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("New() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_presenter_Output(t *testing.T) { + type args struct { + v interface{} + } + tests := []struct { + name string + p *presenter + args args + want string + wantErr bool + }{ + { + name: "Jsonエンコード", + p: &presenter{}, + args: args{ + v: entity.OmikujiResult{ + ID: 1, + Ruck: "大吉", + Message: "メッセージ1", + }, + }, + want: "{\"id\":1,\"ruck\":\"大吉\",\"message\":\"メッセージ1\"}\n", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &presenter{} + got, err := p.Output(tt.args.v) + if (err != nil) != tt.wantErr { + t.Errorf("presenter.Output() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("presenter.Output() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/kadai4/pkg/api/domain/service/omikuji/data.go b/kadai4/pkg/api/domain/service/omikuji/data.go new file mode 100644 index 0000000..d92c164 --- /dev/null +++ b/kadai4/pkg/api/domain/service/omikuji/data.go @@ -0,0 +1,56 @@ +package omikuji + +import entity "omikuji-app/pkg/api/domain/entity/omikuji" + +var omikujiResults = entity.OmikujiResults{ + { + ID: 1, + Ruck: "大吉", + Message: "おめでとうございます!大吉です!", + }, + { + ID: 2, + Ruck: "大吉", + Message: "大吉でした!絶好調です!", + }, + { + ID: 3, + Ruck: "吉", + Message: "吉です!かなりツイてます!", + }, + { + ID: 4, + Ruck: "吉", + Message: "吉です!良い運勢ですね!", + }, + { + ID: 5, + Ruck: "中吉", + Message: "中吉でした!いい感じです!", + }, + { + ID: 6, + Ruck: "中吉", + Message: "なかなかいいですね!中吉です!", + }, + { + ID: 7, + Ruck: "小吉", + Message: "小吉です!悪くないですね!", + }, + { + ID: 8, + Ruck: "小吉", + Message: "小吉です!少しツイてます!", + }, + { + ID: 9, + Ruck: "小吉", + Message: "小吉でした!!!", + }, + { + ID: 10, + Ruck: "凶", + Message: "凶でした!今日も一日頑張りましょう!", + }, +} diff --git a/kadai4/pkg/api/domain/service/omikuji/service.go b/kadai4/pkg/api/domain/service/omikuji/service.go index 1112cc7..7f1b185 100644 --- a/kadai4/pkg/api/domain/service/omikuji/service.go +++ b/kadai4/pkg/api/domain/service/omikuji/service.go @@ -3,63 +3,13 @@ package omikuji import ( "context" - "omikuji-app/pkg/api/ocontext" - entity "omikuji-app/pkg/api/domain/entity/omikuji" + "omikuji-app/pkg/api/ocontext" ) -var rs = entity.OmikujiResults{ - { - ID: 1, - Ruck: "大吉", - Message: "おめでとうございます!大吉です!", - }, - { - ID: 2, - Ruck: "大吉", - Message: "大吉でした!絶好調です!", - }, - { - ID: 3, - Ruck: "吉", - Message: "吉です!かなりツイてます!", - }, - { - ID: 4, - Ruck: "吉", - Message: "吉です!良い運勢ですね!", - }, - { - ID: 5, - Ruck: "中吉", - Message: "中吉でした!いい感じです!", - }, - { - ID: 6, - Ruck: "中吉", - Message: "なかなかいいですね!中吉です!", - }, - { - ID: 7, - Ruck: "小吉", - Message: "小吉です!悪くないですね!", - }, - { - ID: 8, - Ruck: "小吉", - Message: "小吉です!少しツイてます!", - }, - { - ID: 9, - Ruck: "小吉", - Message: "小吉でした!!!", - }, - { - ID: 10, - Ruck: "凶", - Message: "凶でした!今日も一日頑張りましょう!", - }, -} +const dateFormat = "1/2" + +var daikichiOnlyDates = map[string]struct{}{"1/1": {}, "1/2": {}, "1/3": {}} type OmikujiService interface { Draw(ctx context.Context) entity.OmikujiResult @@ -75,8 +25,9 @@ func New() OmikujiService { // Draw おみくじを引く. func (s *omikujiService) Draw(ctx context.Context) entity.OmikujiResult { t := ocontext.GetAccessTime(ctx) - day := t.Format("1/2") - if day == "1/1" || day == "1/2" || day == "1/3" { + rs := omikujiResults + date := t.Format(dateFormat) + if _, exists := daikichiOnlyDates[date]; exists { rs = rs.ExtractByRuck("大吉") } return rs.FindRandom() diff --git a/kadai4/pkg/api/domain/service/omikuji/service_test.go b/kadai4/pkg/api/domain/service/omikuji/service_test.go index 361f77d..4709380 100644 --- a/kadai4/pkg/api/domain/service/omikuji/service_test.go +++ b/kadai4/pkg/api/domain/service/omikuji/service_test.go @@ -38,6 +38,13 @@ func Test_omikujiService_Draw(t *testing.T) { args args want string }{ + { + name: "正月以外のおみくじ", + s: &omikujiService{}, + args: args{ + ctx: ocontext.SetAccessTime(context.Background(), time.Date(2000, 1, 4, 3, 4, 5, 6, time.Local)), + }, + }, { name: "1/2のおみくじ", s: &omikujiService{}, @@ -49,7 +56,8 @@ func Test_omikujiService_Draw(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.s.Draw(tt.args.ctx); !reflect.DeepEqual(got.Ruck, tt.want) { + got := tt.s.Draw(tt.args.ctx) + if tt.want != "" && !reflect.DeepEqual(got.Ruck, tt.want) { t.Errorf("omikujiService.Draw() = %v, want %v", got, tt.want) } }) From ac7b71d6755cf1afbac945840b766f3e2c3830ad Mon Sep 17 00:00:00 2001 From: simady Date: Wed, 14 Aug 2019 19:26:41 +0900 Subject: [PATCH 4/5] =?UTF-8?q?README=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai4/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 kadai4/README.md diff --git a/kadai4/README.md b/kadai4/README.md new file mode 100644 index 0000000..a89ca31 --- /dev/null +++ b/kadai4/README.md @@ -0,0 +1,17 @@ +# 課題4 + +## 内容 +おみくじAPI +- JSON形式でおみくじの結果を返す +- 正月 (1/1-1/3) だけ大吉にする +- ハンドラのテストを書いてみる + +## 実行方法 + +``` +go run cmd/main.go +``` + +## 所感 +アーキテクチャを少しだけ考慮してみました。 +Middleware等のテストをどのように実施するのがいいか悩みました。 From 5dd45a02ff8ef35d054e9319f0390c8f290ae859 Mon Sep 17 00:00:00 2001 From: simady Date: Wed, 14 Aug 2019 19:31:12 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E3=83=87=E3=82=A3=E3=83=AC=E3=82=AF?= =?UTF-8?q?=E3=83=88=E3=83=AA=E6=A7=8B=E9=80=A0=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kadai4/{ => simady}/README.md | 0 kadai4/{ => simady}/cmd/main.go | 0 kadai4/{ => simady}/go.mod | 0 kadai4/{ => simady}/pkg/api/api.go | 0 kadai4/{ => simady}/pkg/api/app/handler/omikuji/handler.go | 0 kadai4/{ => simady}/pkg/api/app/handler/omikuji/handler_test.go | 0 kadai4/{ => simady}/pkg/api/app/interactor/omikuji/interactor.go | 0 .../pkg/api/app/interactor/omikuji/interactor_test.go | 0 .../pkg/api/app/interactor/omikuji/mock/interactor_mock.go | 0 kadai4/{ => simady}/pkg/api/app/middleware/middleware.go | 0 kadai4/{ => simady}/pkg/api/app/middleware/middleware_test.go | 0 kadai4/{ => simady}/pkg/api/app/presenter/mock/presenter_mock.go | 0 kadai4/{ => simady}/pkg/api/app/presenter/presenter.go | 0 kadai4/{ => simady}/pkg/api/app/presenter/presenter_test.go | 0 kadai4/{ => simady}/pkg/api/domain/entity/omikuji/entity.go | 0 kadai4/{ => simady}/pkg/api/domain/entity/omikuji/entity_test.go | 0 kadai4/{ => simady}/pkg/api/domain/service/omikuji/data.go | 0 .../pkg/api/domain/service/omikuji/mock/service_mock.go | 0 kadai4/{ => simady}/pkg/api/domain/service/omikuji/service.go | 0 .../{ => simady}/pkg/api/domain/service/omikuji/service_test.go | 0 kadai4/{ => simady}/pkg/api/ocontext/context.go | 0 kadai4/{ => simady}/pkg/api/ocontext/context_test.go | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename kadai4/{ => simady}/README.md (100%) rename kadai4/{ => simady}/cmd/main.go (100%) rename kadai4/{ => simady}/go.mod (100%) rename kadai4/{ => simady}/pkg/api/api.go (100%) rename kadai4/{ => simady}/pkg/api/app/handler/omikuji/handler.go (100%) rename kadai4/{ => simady}/pkg/api/app/handler/omikuji/handler_test.go (100%) rename kadai4/{ => simady}/pkg/api/app/interactor/omikuji/interactor.go (100%) rename kadai4/{ => simady}/pkg/api/app/interactor/omikuji/interactor_test.go (100%) rename kadai4/{ => simady}/pkg/api/app/interactor/omikuji/mock/interactor_mock.go (100%) rename kadai4/{ => simady}/pkg/api/app/middleware/middleware.go (100%) rename kadai4/{ => simady}/pkg/api/app/middleware/middleware_test.go (100%) rename kadai4/{ => simady}/pkg/api/app/presenter/mock/presenter_mock.go (100%) rename kadai4/{ => simady}/pkg/api/app/presenter/presenter.go (100%) rename kadai4/{ => simady}/pkg/api/app/presenter/presenter_test.go (100%) rename kadai4/{ => simady}/pkg/api/domain/entity/omikuji/entity.go (100%) rename kadai4/{ => simady}/pkg/api/domain/entity/omikuji/entity_test.go (100%) rename kadai4/{ => simady}/pkg/api/domain/service/omikuji/data.go (100%) rename kadai4/{ => simady}/pkg/api/domain/service/omikuji/mock/service_mock.go (100%) rename kadai4/{ => simady}/pkg/api/domain/service/omikuji/service.go (100%) rename kadai4/{ => simady}/pkg/api/domain/service/omikuji/service_test.go (100%) rename kadai4/{ => simady}/pkg/api/ocontext/context.go (100%) rename kadai4/{ => simady}/pkg/api/ocontext/context_test.go (100%) diff --git a/kadai4/README.md b/kadai4/simady/README.md similarity index 100% rename from kadai4/README.md rename to kadai4/simady/README.md diff --git a/kadai4/cmd/main.go b/kadai4/simady/cmd/main.go similarity index 100% rename from kadai4/cmd/main.go rename to kadai4/simady/cmd/main.go diff --git a/kadai4/go.mod b/kadai4/simady/go.mod similarity index 100% rename from kadai4/go.mod rename to kadai4/simady/go.mod diff --git a/kadai4/pkg/api/api.go b/kadai4/simady/pkg/api/api.go similarity index 100% rename from kadai4/pkg/api/api.go rename to kadai4/simady/pkg/api/api.go diff --git a/kadai4/pkg/api/app/handler/omikuji/handler.go b/kadai4/simady/pkg/api/app/handler/omikuji/handler.go similarity index 100% rename from kadai4/pkg/api/app/handler/omikuji/handler.go rename to kadai4/simady/pkg/api/app/handler/omikuji/handler.go diff --git a/kadai4/pkg/api/app/handler/omikuji/handler_test.go b/kadai4/simady/pkg/api/app/handler/omikuji/handler_test.go similarity index 100% rename from kadai4/pkg/api/app/handler/omikuji/handler_test.go rename to kadai4/simady/pkg/api/app/handler/omikuji/handler_test.go diff --git a/kadai4/pkg/api/app/interactor/omikuji/interactor.go b/kadai4/simady/pkg/api/app/interactor/omikuji/interactor.go similarity index 100% rename from kadai4/pkg/api/app/interactor/omikuji/interactor.go rename to kadai4/simady/pkg/api/app/interactor/omikuji/interactor.go diff --git a/kadai4/pkg/api/app/interactor/omikuji/interactor_test.go b/kadai4/simady/pkg/api/app/interactor/omikuji/interactor_test.go similarity index 100% rename from kadai4/pkg/api/app/interactor/omikuji/interactor_test.go rename to kadai4/simady/pkg/api/app/interactor/omikuji/interactor_test.go diff --git a/kadai4/pkg/api/app/interactor/omikuji/mock/interactor_mock.go b/kadai4/simady/pkg/api/app/interactor/omikuji/mock/interactor_mock.go similarity index 100% rename from kadai4/pkg/api/app/interactor/omikuji/mock/interactor_mock.go rename to kadai4/simady/pkg/api/app/interactor/omikuji/mock/interactor_mock.go diff --git a/kadai4/pkg/api/app/middleware/middleware.go b/kadai4/simady/pkg/api/app/middleware/middleware.go similarity index 100% rename from kadai4/pkg/api/app/middleware/middleware.go rename to kadai4/simady/pkg/api/app/middleware/middleware.go diff --git a/kadai4/pkg/api/app/middleware/middleware_test.go b/kadai4/simady/pkg/api/app/middleware/middleware_test.go similarity index 100% rename from kadai4/pkg/api/app/middleware/middleware_test.go rename to kadai4/simady/pkg/api/app/middleware/middleware_test.go diff --git a/kadai4/pkg/api/app/presenter/mock/presenter_mock.go b/kadai4/simady/pkg/api/app/presenter/mock/presenter_mock.go similarity index 100% rename from kadai4/pkg/api/app/presenter/mock/presenter_mock.go rename to kadai4/simady/pkg/api/app/presenter/mock/presenter_mock.go diff --git a/kadai4/pkg/api/app/presenter/presenter.go b/kadai4/simady/pkg/api/app/presenter/presenter.go similarity index 100% rename from kadai4/pkg/api/app/presenter/presenter.go rename to kadai4/simady/pkg/api/app/presenter/presenter.go diff --git a/kadai4/pkg/api/app/presenter/presenter_test.go b/kadai4/simady/pkg/api/app/presenter/presenter_test.go similarity index 100% rename from kadai4/pkg/api/app/presenter/presenter_test.go rename to kadai4/simady/pkg/api/app/presenter/presenter_test.go diff --git a/kadai4/pkg/api/domain/entity/omikuji/entity.go b/kadai4/simady/pkg/api/domain/entity/omikuji/entity.go similarity index 100% rename from kadai4/pkg/api/domain/entity/omikuji/entity.go rename to kadai4/simady/pkg/api/domain/entity/omikuji/entity.go diff --git a/kadai4/pkg/api/domain/entity/omikuji/entity_test.go b/kadai4/simady/pkg/api/domain/entity/omikuji/entity_test.go similarity index 100% rename from kadai4/pkg/api/domain/entity/omikuji/entity_test.go rename to kadai4/simady/pkg/api/domain/entity/omikuji/entity_test.go diff --git a/kadai4/pkg/api/domain/service/omikuji/data.go b/kadai4/simady/pkg/api/domain/service/omikuji/data.go similarity index 100% rename from kadai4/pkg/api/domain/service/omikuji/data.go rename to kadai4/simady/pkg/api/domain/service/omikuji/data.go diff --git a/kadai4/pkg/api/domain/service/omikuji/mock/service_mock.go b/kadai4/simady/pkg/api/domain/service/omikuji/mock/service_mock.go similarity index 100% rename from kadai4/pkg/api/domain/service/omikuji/mock/service_mock.go rename to kadai4/simady/pkg/api/domain/service/omikuji/mock/service_mock.go diff --git a/kadai4/pkg/api/domain/service/omikuji/service.go b/kadai4/simady/pkg/api/domain/service/omikuji/service.go similarity index 100% rename from kadai4/pkg/api/domain/service/omikuji/service.go rename to kadai4/simady/pkg/api/domain/service/omikuji/service.go diff --git a/kadai4/pkg/api/domain/service/omikuji/service_test.go b/kadai4/simady/pkg/api/domain/service/omikuji/service_test.go similarity index 100% rename from kadai4/pkg/api/domain/service/omikuji/service_test.go rename to kadai4/simady/pkg/api/domain/service/omikuji/service_test.go diff --git a/kadai4/pkg/api/ocontext/context.go b/kadai4/simady/pkg/api/ocontext/context.go similarity index 100% rename from kadai4/pkg/api/ocontext/context.go rename to kadai4/simady/pkg/api/ocontext/context.go diff --git a/kadai4/pkg/api/ocontext/context_test.go b/kadai4/simady/pkg/api/ocontext/context_test.go similarity index 100% rename from kadai4/pkg/api/ocontext/context_test.go rename to kadai4/simady/pkg/api/ocontext/context_test.go