From 407bac15233d2f9333da103333b151a56e55b127 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 31 Mar 2021 22:02:36 -0400 Subject: [PATCH 1/3] Test get Stores --- 08-automated_tests/internal/fetching/beer.go | 25 +++++++ .../internal/fetching/service.go | 33 +++------ .../internal/fetching/service_test.go | 73 +++++++++++++++++-- 08-automated_tests/internal/fetching/store.go | 25 +++++++ .../internal/storage/mock/store.go | 16 ++++ 08-automated_tests/internal/store.go | 23 ++++++ 6 files changed, 164 insertions(+), 31 deletions(-) create mode 100644 08-automated_tests/internal/fetching/beer.go create mode 100644 08-automated_tests/internal/fetching/store.go create mode 100644 08-automated_tests/internal/storage/mock/store.go create mode 100644 08-automated_tests/internal/store.go diff --git a/08-automated_tests/internal/fetching/beer.go b/08-automated_tests/internal/fetching/beer.go new file mode 100644 index 0000000..a22643e --- /dev/null +++ b/08-automated_tests/internal/fetching/beer.go @@ -0,0 +1,25 @@ +package fetching + +import ( + beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" + "github.com/pkg/errors" +) + +func (s *service) FetchBeers() ([]beerscli.Beer, error) { + return s.bR.GetBeers() +} + +func (s *service) FetchByID(id int) (beerscli.Beer, error) { + beers, err := s.FetchBeers() + if err != nil { + return beerscli.Beer{}, err + } + + for _, beer := range beers { + if beer.ProductID == id { + return beer, nil + } + } + + return beerscli.Beer{}, errors.Errorf("Beer %d not found", id) +} diff --git a/08-automated_tests/internal/fetching/service.go b/08-automated_tests/internal/fetching/service.go index 1b32c31..747feeb 100644 --- a/08-automated_tests/internal/fetching/service.go +++ b/08-automated_tests/internal/fetching/service.go @@ -2,7 +2,6 @@ package fetching import ( beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" - "github.com/pkg/errors" ) // Service provides beer fetching operations @@ -11,32 +10,20 @@ type Service interface { FetchBeers() ([]beerscli.Beer, error) // FetchByID filter all beers and get only the beer that match with given id FetchByID(id int) (beerscli.Beer, error) + // FetchBeers fetch all beers from repository + + // FetchStores fetch all stores from repository + FetchStores() ([]beerscli.Store, error) + // FetchStoreByID filter all stores and get only the store that match with given id + FetchStoreByID(id int) (beerscli.Store, error) } type service struct { - bR beerscli.BeerRepo + bR beerscli.BeerRepo + storeRepo beerscli.StoreRepo } // NewService creates an adding service with the necessary dependencies -func NewService(r beerscli.BeerRepo) Service { - return &service{r} -} - -func (s *service) FetchBeers() ([]beerscli.Beer, error) { - return s.bR.GetBeers() -} - -func (s *service) FetchByID(id int) (beerscli.Beer, error) { - beers, err := s.FetchBeers() - if err != nil { - return beerscli.Beer{}, err - } - - for _, beer := range beers { - if beer.ProductID == id { - return beer, nil - } - } - - return beerscli.Beer{}, errors.Errorf("Beer %d not found", id) +func NewService(beerRepo beerscli.BeerRepo, storeRepo beerscli.StoreRepo) Service { + return &service{beerRepo, storeRepo} } diff --git a/08-automated_tests/internal/fetching/service_test.go b/08-automated_tests/internal/fetching/service_test.go index 9a3b221..b1f8de3 100644 --- a/08-automated_tests/internal/fetching/service_test.go +++ b/08-automated_tests/internal/fetching/service_test.go @@ -13,19 +13,20 @@ import ( func TestFetchByID(t *testing.T) { tests := map[string]struct { - repo beerscli.BeerRepo - input int - want int - err error + beerRepo beerscli.BeerRepo + storeRepo beerscli.StoreRepo + input int + want int + err error }{ - "valid beer": {repo: buildMockBeers(), input: 127, want: 127, err: nil}, - "not found beer": {repo: buildMockBeers(), input: 99999, err: errors.New("error")}, - "error with repository": {repo: buildMockError(), err: errors.New("error")}, + "valid beer": {beerRepo: buildMockBeers(), input: 127, want: 127, err: nil}, + "not found beer": {beerRepo: buildMockBeers(), input: 99999, err: errors.New("error")}, + "error with repository": {beerRepo: buildMockError(), err: errors.New("error")}, } for name, tc := range tests { t.Run(name, func(t *testing.T) { - service := NewService(tc.repo) + service := NewService(tc.beerRepo, tc.storeRepo) b, err := service.FetchByID(tc.input) @@ -80,3 +81,59 @@ func buildMockError() beerscli.BeerRepo { return mockedRepo } + +func TestGetStores(t *testing.T) { + storeRepo := new(mock.MockStoreRepo) + stores := []beerscli.Store{ + { + StoreID: 1, + Name: "Paceña", + Country: "BOB", + }, + } + storeRepo.On("GetStores").Return(stores, nil) + + service := NewService(nil, storeRepo) + + stores, err := service.FetchStores() + + assert.Nil(t, err) + + assert.Equal(t, 1, stores[0].StoreID) + assert.Equal(t, "Paceña", stores[0].Name) + assert.Equal(t, "BOB", stores[0].Country) +} + +func TestFetchStoreByID(t *testing.T) { + tests := map[string]struct { + input int + want int + err error + }{ + "valid beer": {input: 127, want: 127, err: nil}, + "not found beer": {input: 99999, err: errors.New("error")}, + //"error with repository": {err: errors.New("error")}, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + storeRepo := new(mock.MockStoreRepo) + stores := []beerscli.Store{ + { + StoreID: 1, + Name: "Paceña", + Country: "BOB", + }, + } + storeRepo.On("GetStores").Return(stores, nil) + + service := NewService(nil, storeRepo) + + stores, err := service.FetchStores() + + assert.Equal(t, tc.err, err) + assert.Equal(t, "Paceña", stores[0].Name) + + }) + } +} diff --git a/08-automated_tests/internal/fetching/store.go b/08-automated_tests/internal/fetching/store.go new file mode 100644 index 0000000..45af57f --- /dev/null +++ b/08-automated_tests/internal/fetching/store.go @@ -0,0 +1,25 @@ +package fetching + +import ( + beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" + "github.com/pkg/errors" +) + +func (s *service) FetchStores() ([]beerscli.Store, error) { + return s.storeRepo.GetStores() +} + +func (s *service) FetchStoreByID(id int) (beerscli.Store, error) { + stores, err := s.FetchStores() + if err != nil { + return beerscli.Store{}, err + } + + for _, store := range stores { + if store.StoreID == id { + return store, nil + } + } + + return beerscli.Store{}, errors.Errorf("Store %d not found", id) +} diff --git a/08-automated_tests/internal/storage/mock/store.go b/08-automated_tests/internal/storage/mock/store.go new file mode 100644 index 0000000..4485c02 --- /dev/null +++ b/08-automated_tests/internal/storage/mock/store.go @@ -0,0 +1,16 @@ +package mock + +import ( + beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" + "github.com/stretchr/testify/mock" +) + +type MockStoreRepo struct { + mock.Mock +} + +func (m *MockStoreRepo) GetStores() ([]beerscli.Store, error) { + args := m.Called() + res := args.Get(0) + return res.([]beerscli.Store), args.Error(1) +} diff --git a/08-automated_tests/internal/store.go b/08-automated_tests/internal/store.go new file mode 100644 index 0000000..2d31d70 --- /dev/null +++ b/08-automated_tests/internal/store.go @@ -0,0 +1,23 @@ +package beerscli + +// Store representation of beer into data struct +type Store struct { + StoreID int `json:"product_id"` + Name string `json:"name"` + Country string `json:"country"` +} + +// StoreRepo definiton of methods to access a data beer +type StoreRepo interface { + GetStores() ([]Store, error) +} + +// NewStore initialize struct beer +func NewStore(productID int, name, category, brewer, country, price string) (b Store) { + b = Store{ + StoreID: productID, + Name: name, + Country: country, + } + return +} From 96e0b513d280bfd0a340d426275b167bc53ccae3 Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 31 Mar 2021 23:31:45 -0400 Subject: [PATCH 2/3] Test fetch store by ID --- 08-automated_tests/cmd/beers-cli/main.go | 3 +- .../internal/fetching/service_test.go | 42 +++++++++++-------- .../internal/storage/csv/store_repository.go | 42 +++++++++++++++++++ .../internal/storage/mock/store.go | 6 +++ 08-automated_tests/internal/store.go | 4 +- 5 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 08-automated_tests/internal/storage/csv/store_repository.go diff --git a/08-automated_tests/cmd/beers-cli/main.go b/08-automated_tests/cmd/beers-cli/main.go index 034cbb8..92d852b 100644 --- a/08-automated_tests/cmd/beers-cli/main.go +++ b/08-automated_tests/cmd/beers-cli/main.go @@ -24,7 +24,8 @@ func main() { repo = ontario.NewOntarioRepository() } - fetchingService := fetching.NewService(repo) + storeRepo := csv.NewCSVStoreRepo() + fetchingService := fetching.NewService(repo, storeRepo) rootCmd := &cobra.Command{Use: "beers-cli"} rootCmd.AddCommand(cli.InitBeersCmd(fetchingService)) diff --git a/08-automated_tests/internal/fetching/service_test.go b/08-automated_tests/internal/fetching/service_test.go index b1f8de3..32203e2 100644 --- a/08-automated_tests/internal/fetching/service_test.go +++ b/08-automated_tests/internal/fetching/service_test.go @@ -2,6 +2,7 @@ package fetching import ( "errors" + "fmt" "testing" beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" @@ -86,7 +87,7 @@ func TestGetStores(t *testing.T) { storeRepo := new(mock.MockStoreRepo) stores := []beerscli.Store{ { - StoreID: 1, + StoreID: 100, Name: "Paceña", Country: "BOB", }, @@ -99,40 +100,45 @@ func TestGetStores(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, 1, stores[0].StoreID) + assert.Equal(t, 100, stores[0].StoreID) assert.Equal(t, "Paceña", stores[0].Name) assert.Equal(t, "BOB", stores[0].Country) } func TestFetchStoreByID(t *testing.T) { + stores := []beerscli.Store{ + { + StoreID: 100, + Name: "Paceña", + Country: "BOB", + }, + } tests := map[string]struct { - input int - want int - err error + inputID int + expectedName string + stores []beerscli.Store + err error }{ - "valid beer": {input: 127, want: 127, err: nil}, - "not found beer": {input: 99999, err: errors.New("error")}, - //"error with repository": {err: errors.New("error")}, + "valid store": {inputID: 100, expectedName: "Paceña", stores: stores, err: nil}, + "not found store": {inputID: 99999, stores: stores, err: errors.New("error")}, + "error with repository": {stores: nil, err: errors.New("error")}, } for name, tc := range tests { t.Run(name, func(t *testing.T) { + fmt.Println(tc.inputID) storeRepo := new(mock.MockStoreRepo) - stores := []beerscli.Store{ - { - StoreID: 1, - Name: "Paceña", - Country: "BOB", - }, - } - storeRepo.On("GetStores").Return(stores, nil) + storeRepo.On("GetStores").Return(tc.stores, tc.err) service := NewService(nil, storeRepo) - stores, err := service.FetchStores() + store, err := service.FetchStoreByID(tc.inputID) assert.Equal(t, tc.err, err) - assert.Equal(t, "Paceña", stores[0].Name) + + if tc.err == nil { + assert.Equal(t, tc.expectedName, store.Name) + } }) } diff --git a/08-automated_tests/internal/storage/csv/store_repository.go b/08-automated_tests/internal/storage/csv/store_repository.go new file mode 100644 index 0000000..43faf17 --- /dev/null +++ b/08-automated_tests/internal/storage/csv/store_repository.go @@ -0,0 +1,42 @@ +package csv + +import ( + "bufio" + "os" + "strconv" + "strings" + + beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" +) + +type storeRepo struct { +} + +// NewRepository initialize csv repository +func NewCSVStoreRepo() beerscli.StoreRepo { + return &storeRepo{} +} + +// GetBeers fetch beers data from csv +func (r *storeRepo) GetStores() ([]beerscli.Store, error) { + f, _ := os.Open("08-automated_tests/data/stores.csv") + reader := bufio.NewReader(f) + + var stores []beerscli.Store + + for line := readLine(reader); line != nil; line = readLine(reader) { + values := strings.Split(string(line), ",") + + storeID, _ := strconv.Atoi(values[0]) + + store := beerscli.NewStore( + storeID, + values[1], + values[2], + ) + + stores = append(stores, store) + } + + return stores, nil +} diff --git a/08-automated_tests/internal/storage/mock/store.go b/08-automated_tests/internal/storage/mock/store.go index 4485c02..26ded94 100644 --- a/08-automated_tests/internal/storage/mock/store.go +++ b/08-automated_tests/internal/storage/mock/store.go @@ -14,3 +14,9 @@ func (m *MockStoreRepo) GetStores() ([]beerscli.Store, error) { res := args.Get(0) return res.([]beerscli.Store), args.Error(1) } + +//func (m *MockStoreRepo) FetchStoreByID(ID int) (beerscli.Store, error) { +// args := m.Called(ID) +// res := args.Get(0) +// return res.(beerscli.Store), args.Error(1) +//} diff --git a/08-automated_tests/internal/store.go b/08-automated_tests/internal/store.go index 2d31d70..3e5187a 100644 --- a/08-automated_tests/internal/store.go +++ b/08-automated_tests/internal/store.go @@ -13,9 +13,9 @@ type StoreRepo interface { } // NewStore initialize struct beer -func NewStore(productID int, name, category, brewer, country, price string) (b Store) { +func NewStore(storeID int, name, country string) (b Store) { b = Store{ - StoreID: productID, + StoreID: storeID, Name: name, Country: country, } From 3913e28d9ecb357d21309e7fc2b3186b3cae9a3b Mon Sep 17 00:00:00 2001 From: David Callizaya Date: Wed, 31 Mar 2021 23:40:30 -0400 Subject: [PATCH 3/3] Clean code --- 08-automated_tests/internal/fetching/service.go | 1 - 08-automated_tests/internal/storage/csv/store_repository.go | 4 ++-- 08-automated_tests/internal/storage/mock/store.go | 6 ------ 08-automated_tests/internal/store.go | 4 ++-- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/08-automated_tests/internal/fetching/service.go b/08-automated_tests/internal/fetching/service.go index 747feeb..040c682 100644 --- a/08-automated_tests/internal/fetching/service.go +++ b/08-automated_tests/internal/fetching/service.go @@ -10,7 +10,6 @@ type Service interface { FetchBeers() ([]beerscli.Beer, error) // FetchByID filter all beers and get only the beer that match with given id FetchByID(id int) (beerscli.Beer, error) - // FetchBeers fetch all beers from repository // FetchStores fetch all stores from repository FetchStores() ([]beerscli.Store, error) diff --git a/08-automated_tests/internal/storage/csv/store_repository.go b/08-automated_tests/internal/storage/csv/store_repository.go index 43faf17..a780edb 100644 --- a/08-automated_tests/internal/storage/csv/store_repository.go +++ b/08-automated_tests/internal/storage/csv/store_repository.go @@ -12,12 +12,12 @@ import ( type storeRepo struct { } -// NewRepository initialize csv repository +// NewCSVStoreRepo initialize csv repository func NewCSVStoreRepo() beerscli.StoreRepo { return &storeRepo{} } -// GetBeers fetch beers data from csv +// GetStores fetch stores data from csv func (r *storeRepo) GetStores() ([]beerscli.Store, error) { f, _ := os.Open("08-automated_tests/data/stores.csv") reader := bufio.NewReader(f) diff --git a/08-automated_tests/internal/storage/mock/store.go b/08-automated_tests/internal/storage/mock/store.go index 26ded94..4485c02 100644 --- a/08-automated_tests/internal/storage/mock/store.go +++ b/08-automated_tests/internal/storage/mock/store.go @@ -14,9 +14,3 @@ func (m *MockStoreRepo) GetStores() ([]beerscli.Store, error) { res := args.Get(0) return res.([]beerscli.Store), args.Error(1) } - -//func (m *MockStoreRepo) FetchStoreByID(ID int) (beerscli.Store, error) { -// args := m.Called(ID) -// res := args.Get(0) -// return res.(beerscli.Store), args.Error(1) -//} diff --git a/08-automated_tests/internal/store.go b/08-automated_tests/internal/store.go index 3e5187a..d000d0d 100644 --- a/08-automated_tests/internal/store.go +++ b/08-automated_tests/internal/store.go @@ -7,12 +7,12 @@ type Store struct { Country string `json:"country"` } -// StoreRepo definiton of methods to access a data beer +// StoreRepo definiton of methods to access stores data type StoreRepo interface { GetStores() ([]Store, error) } -// NewStore initialize struct beer +// NewStore initialize struct Store func NewStore(storeID int, name, country string) (b Store) { b = Store{ StoreID: storeID,