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/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..040c682 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,19 @@ 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) + + // 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..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" @@ -13,19 +14,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 +82,64 @@ func buildMockError() beerscli.BeerRepo { return mockedRepo } + +func TestGetStores(t *testing.T) { + storeRepo := new(mock.MockStoreRepo) + stores := []beerscli.Store{ + { + StoreID: 100, + 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, 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 { + inputID int + expectedName string + stores []beerscli.Store + err 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) + storeRepo.On("GetStores").Return(tc.stores, tc.err) + + service := NewService(nil, storeRepo) + + store, err := service.FetchStoreByID(tc.inputID) + + assert.Equal(t, tc.err, err) + + if tc.err == nil { + assert.Equal(t, tc.expectedName, store.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/csv/store_repository.go b/08-automated_tests/internal/storage/csv/store_repository.go new file mode 100644 index 0000000..a780edb --- /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 { +} + +// NewCSVStoreRepo initialize csv repository +func NewCSVStoreRepo() beerscli.StoreRepo { + return &storeRepo{} +} + +// 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) + + 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 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..d000d0d --- /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 stores data +type StoreRepo interface { + GetStores() ([]Store, error) +} + +// NewStore initialize struct Store +func NewStore(storeID int, name, country string) (b Store) { + b = Store{ + StoreID: storeID, + Name: name, + Country: country, + } + return +}