1
0
Fork 0
test/internal/store/store_test.go

345 lines
11 KiB
Go

package store
import (
"database/sql"
"testing"
"github.com/DATA-DOG/go-sqlmock"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"gitlab.com/toby3d/test/internal/model"
)
func newDataBase(t *testing.T) (*sqlx.DB, sqlmock.Sqlmock, func()) {
db, mock, err := sqlmock.New()
if !assert.NoError(t, err) {
assert.FailNow(t, err.Error())
}
return sqlx.NewDb(db, "sqlmock"), mock, func() { assert.NoError(t, mock.ExpectationsWereMet()) }
}
func TestAdd(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
s := NewCartStore(db)
itemOne := model.Item{ProductId: 42, Quanity: 24}
itemTwo := model.Item{ProductId: 24, Quanity: 42}
t.Run("invalid", func(t *testing.T) {
t.Run("empty", func(t *testing.T) {
assert.Error(t, s.Add(&model.Item{}))
count, list := s.GetList()
assert.Empty(t, list, 0)
assert.Zero(t, count)
})
t.Run("zero quanity", func(t *testing.T) {
assert.Error(t, s.Add(&model.Item{ProductId: 42}))
count, list := s.GetList()
assert.Empty(t, list, 0)
assert.Zero(t, count)
})
t.Run("not exists product", func(t *testing.T) {
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).
WillReturnError(sql.ErrNoRows)
assert.Error(t, s.Add(&model.Item{ProductId: 420, Quanity: 7}))
})
})
t.Run("valid", func(t *testing.T) {
t.Run("single", func(t *testing.T) {
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).WillReturnRows(
mock.NewRows([]string{"id", "name", "price"}).
AddRow(itemOne.GetProductId(), "Apple", 4.99),
)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`)
mock.ExpectExec(`INSERT INTO cart`).
WithArgs(itemOne.GetProductId(), itemOne.GetQuanity()).
WillReturnResult(sqlmock.NewResult(int64(itemOne.GetProductId()), 1))
assert.NoError(t, s.Add(&itemOne))
mock.ExpectQuery(`SELECT \* FROM cart`).
WillReturnRows(sqlmock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()),
)
count, list := s.GetList()
assert.Contains(t, list, &itemOne)
assert.Equal(t, 1, count)
})
t.Run("append", func(t *testing.T) {
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).WillReturnRows(
mock.NewRows([]string{"id", "name", "price"}).
AddRow(itemOne.GetProductId(), "Apple", 4.99),
)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`).
WillReturnRows(mock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()),
)
mock.ExpectExec(`UPDATE cart SET quanity`).
WithArgs(itemOne.GetProductId(), itemOne.GetQuanity()+6).
WillReturnResult(sqlmock.NewResult(int64(itemOne.GetProductId()), 1))
assert.NoError(t, s.Add(&model.Item{
ProductId: itemOne.GetProductId(),
Quanity: 6,
}))
mock.ExpectQuery(`SELECT \* FROM cart`).
WillReturnRows(sqlmock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()+6),
)
count, list := s.GetList()
assert.Equal(t, 1, count)
assert.Contains(t, list, &model.Item{
ProductId: itemOne.ProductId,
Quanity: itemOne.GetQuanity() + 6,
})
})
t.Run("add different", func(t *testing.T) {
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).WillReturnRows(
mock.NewRows([]string{"id", "name", "price"}).
AddRow(itemTwo.GetProductId(), "Banana", 2.49),
)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`)
mock.ExpectExec(`INSERT INTO cart`).
WithArgs(itemTwo.GetProductId(), itemTwo.GetQuanity()).
WillReturnResult(sqlmock.NewResult(int64(itemTwo.GetProductId()), 1))
assert.NoError(t, s.Add(&itemTwo))
mock.ExpectQuery(`SELECT \* FROM cart`).
WillReturnRows(sqlmock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()).
AddRow(itemTwo.GetProductId(), itemTwo.GetQuanity()),
)
count, list := s.GetList()
assert.Equal(t, 2, count)
assert.Contains(t, list, &itemOne)
assert.Contains(t, list, &itemTwo)
})
})
}
func TestDelete(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
t.Run("invalid", func(t *testing.T) {
mock.ExpectExec(`DELETE FROM cart WHERE product_id`).WithArgs(240)
assert.Error(t, NewCartStore(db).Delete(240))
})
t.Run("valid", func(t *testing.T) {
mock.ExpectExec(`DELETE FROM cart WHERE product_id`).WithArgs(42).
WillReturnResult(sqlmock.NewResult(42, 1))
assert.NoError(t, NewCartStore(db).Delete(42))
})
}
func TestGetById(t *testing.T) {
t.Run("cart", func(t *testing.T) {
t.Run("invalid", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`).WithArgs(24).
WillReturnError(sql.ErrNoRows)
assert.Nil(t, NewCartStore(db).GetById(24))
})
t.Run("valid", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`).WithArgs(42).
WillReturnRows(mock.NewRows([]string{"product_id", "quanity"}).AddRow(42, 24))
assert.Equal(t, &model.Item{
ProductId: 42,
Quanity: 24,
}, NewCartStore(db).GetById(42))
})
})
t.Run("product", func(t *testing.T) {
t.Run("invalid", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).WithArgs(24).
WillReturnError(sql.ErrNoRows)
assert.Nil(t, NewProductStore(db).GetById(24))
})
t.Run("valid", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).WithArgs(42).
WillReturnRows(
mock.NewRows([]string{"id", "name", "price"}).AddRow(42, "Apple", 4.99),
)
assert.Equal(t, &model.Product{
Id: 42,
Name: "Apple",
Price: 4.99,
}, NewProductStore(db).GetById(42))
})
})
}
func TestGetList(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
mock.ExpectQuery(`SELECT \* FROM cart ORDER BY product_id ASC`).
WillReturnRows(mock.NewRows([]string{"product_id", "quanity"}).
AddRow(24, 7).
AddRow(420, 11).
AddRow(42, 24),
)
count, list := NewCartStore(db).GetList()
assert.Equal(t, 3, count)
assert.Contains(t, list, &model.Item{ProductId: 24, Quanity: 7})
assert.Contains(t, list, &model.Item{ProductId: 42, Quanity: 24})
assert.Contains(t, list, &model.Item{ProductId: 420, Quanity: 11})
}
func TestUpdate(t *testing.T) {
itemOne := model.Item{ProductId: 42, Quanity: 16}
t.Run("invalid", func(t *testing.T) {
t.Run("empty", func(t *testing.T) {
db, _, release := newDataBase(t)
defer release()
s := NewCartStore(db)
assert.Error(t, s.Update(&model.Item{}))
count, list := s.GetList()
assert.Empty(t, list)
assert.Zero(t, count)
})
t.Run("zero quanity", func(t *testing.T) {
db, _, release := newDataBase(t)
defer release()
s := NewCartStore(db)
assert.Error(t, s.Update(&model.Item{ProductId: itemOne.ProductId}))
count, list := s.GetList()
assert.Empty(t, list)
assert.Zero(t, count)
})
t.Run("non exists product", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
s := NewCartStore(db)
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).
WillReturnError(sql.ErrNoRows)
assert.Error(t, s.Update(&itemOne))
count, list := s.GetList()
assert.Empty(t, list)
assert.Zero(t, count)
})
})
t.Run("valid", func(t *testing.T) {
t.Run("create", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
s := NewCartStore(db)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`)
mock.ExpectQuery(`SELECT \* FROM products WHERE id`).WillReturnRows(
mock.NewRows([]string{"id", "name", "price"}).
AddRow(itemOne.GetProductId(), "Apple", 4.99),
)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`)
mock.ExpectExec(`INSERT INTO cart`).
WithArgs(itemOne.GetProductId(), itemOne.GetQuanity()).
WillReturnResult(sqlmock.NewResult(int64(itemOne.GetProductId()), 1))
assert.NoError(t, s.Update(&itemOne))
mock.ExpectQuery(`SELECT \* FROM cart`).
WillReturnRows(sqlmock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()),
)
count, list := s.GetList()
assert.Contains(t, list, &itemOne)
assert.Equal(t, 1, count)
})
t.Run("change", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
s := NewCartStore(db)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`).
WillReturnRows(mock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()),
)
mock.ExpectExec(`UPDATE cart SET quanity`).
WithArgs(itemOne.GetProductId(), 7).
WillReturnResult(sqlmock.NewResult(int64(itemOne.GetProductId()), 1))
assert.NoError(t, s.Update(&model.Item{
ProductId: itemOne.GetProductId(),
Quanity: 7,
}))
mock.ExpectQuery(`SELECT \* FROM cart`).
WillReturnRows(sqlmock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), 7),
)
count, list := s.GetList()
assert.Len(t, list, 1, "length of items store must not be changed")
assert.Equal(t, 1, count)
assert.Contains(t, list, &model.Item{
ProductId: itemOne.GetProductId(),
Quanity: 7,
})
})
t.Run("remove", func(t *testing.T) {
t.Run("zero", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
s := NewCartStore(db)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`).
WillReturnRows(mock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()),
)
mock.ExpectExec(`DELETE FROM cart WHERE product_id`).WithArgs(itemOne.GetProductId()).
WillReturnResult(sqlmock.NewResult(int64(itemOne.GetProductId()), 1))
assert.NoError(t, s.Update(&model.Item{
ProductId: itemOne.ProductId,
Quanity: itemOne.Quanity * 0,
}))
count, list := s.GetList()
assert.Empty(t, list)
assert.Zero(t, count)
})
t.Run("less than quanity", func(t *testing.T) {
db, mock, release := newDataBase(t)
defer release()
s := NewCartStore(db)
mock.ExpectQuery(`SELECT \* FROM cart WHERE product_id`).
WillReturnRows(mock.NewRows([]string{"product_id", "quanity"}).
AddRow(itemOne.GetProductId(), itemOne.GetQuanity()),
)
mock.ExpectExec(`DELETE FROM cart WHERE product_id`).WithArgs(itemOne.GetProductId()).
WillReturnResult(sqlmock.NewResult(int64(itemOne.GetProductId()), 1))
assert.NoError(t, s.Update(&model.Item{
ProductId: itemOne.ProductId,
Quanity: itemOne.Quanity * -1,
}))
count, list := s.GetList()
assert.Empty(t, list)
assert.Zero(t, count)
})
})
})
}