Select Git revision
caching_middleware_test.go 7.65 KiB
package middleware
import (
"context"
"testing"
"time"
"git.perx.ru/perxis/perxis-go/pkg/cache"
"git.perx.ru/perxis/perxis-go/pkg/errors"
"git.perx.ru/perxis/perxis-go/pkg/roles"
rsmocks "git.perx.ru/perxis/perxis-go/pkg/roles/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestRolesCache(t *testing.T) {
const (
roleID = "roleID"
spaceID = "spaceID"
size = 5
ttl = 20 * time.Millisecond
)
errNotFound := errors.NotFound(errors.New("not found"))
ctx := context.Background()
t.Run("Get from cache", func(t *testing.T) {
rl := &rsmocks.Roles{}
svc := CachingMiddleware(cache.NewCache(size, ttl))(rl)
rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "Role"}, nil).Once()
v1, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
v2, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.")
rl.AssertExpectations(t)
})
t.Run("List from cache", func(t *testing.T) {
rl := &rsmocks.Roles{}
svc := CachingMiddleware(cache.NewCache(size, ttl))(rl)
rl.On("List", mock.Anything, spaceID).Return([]*roles.Role{{ID: roleID, SpaceID: spaceID, Description: "Role"}}, nil).Once()
vl1, err := svc.List(ctx, spaceID)
require.NoError(t, err)
vl2, err := svc.List(ctx, spaceID)
require.NoError(t, err)
assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.")
rl.AssertExpectations(t)
})
t.Run("Invalidate cache", func(t *testing.T) {
t.Run("After Update", func(t *testing.T) {
rl := &rsmocks.Roles{}
svc := CachingMiddleware(cache.NewCache(size, ttl))(rl)
rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "Role"}, nil).Once()
rl.On("List", mock.Anything, spaceID).Return([]*roles.Role{{ID: roleID, SpaceID: spaceID, Description: "Role"}}, nil).Once()
v1, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
v2, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объектов из кэша.")
vl1, err := svc.List(ctx, spaceID)
require.NoError(t, err)
vl2, err := svc.List(ctx, spaceID)
require.NoError(t, err)
assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.")
rl.On("Update", mock.Anything, mock.Anything).Return(nil).Once()
err = svc.Update(ctx, &roles.Role{ID: roleID, SpaceID: spaceID, Description: "RoleUPD"})
require.NoError(t, err)
rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "RoleUPD"}, nil).Once()
rl.On("List", mock.Anything, spaceID).Return([]*roles.Role{{ID: roleID, SpaceID: spaceID, Description: "RoleUPD"}}, nil).Once()
v3, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
assert.NotSame(t, v2, v3, "Ожидается что кеш объекта был удален после его обновления и объект был запрошен из сервиса.")
vl3, err := svc.List(ctx, spaceID)
require.NoError(t, err)
assert.NotSame(t, vl2[0], vl3[0], "Ожидается что кеш объектов был удален после обновления объекта.")
rl.AssertExpectations(t)
})
t.Run("After Delete", func(t *testing.T) {
rl := &rsmocks.Roles{}
svc := CachingMiddleware(cache.NewCache(size, ttl))(rl)
rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "Role"}, nil).Once()
rl.On("List", mock.Anything, spaceID).Return([]*roles.Role{{ID: roleID, SpaceID: spaceID, Description: "Role"}}, nil).Once()
v1, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
v2, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
assert.Same(t, v1, v2, "Ожидается при повторном запросе получение объекта из кэша.")
vl1, err := svc.List(ctx, spaceID)
require.NoError(t, err)
vl2, err := svc.List(ctx, spaceID)
require.NoError(t, err)
assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объектов из кэша.")
rl.On("Update", mock.Anything, mock.Anything).Return(nil).Once()
err = svc.Update(ctx, &roles.Role{ID: roleID, SpaceID: spaceID, Description: "RoleUPD"})
require.NoError(t, err)
rl.On("Get", mock.Anything, spaceID, roleID).Return(nil, errNotFound).Once()
rl.On("List", mock.Anything, spaceID).Return(nil, errNotFound).Once()
v3, err := svc.Get(ctx, spaceID, roleID)
require.Error(t, err)
assert.EqualError(t, err, "not found", "Ожидается что после удаления кеш объекта был удален и получена ошибка сервиса.")
assert.Nil(t, v3)
vl3, err := svc.List(ctx, spaceID)
require.Error(t, err)
assert.EqualError(t, err, "not found", "Ожидается что после удаления кеш объекта был удален и получена ошибка сервиса.")
assert.Nil(t, vl3)
rl.AssertExpectations(t)
})
t.Run("After Create", func(t *testing.T) {
rl := &rsmocks.Roles{}
svc := CachingMiddleware(cache.NewCache(size, ttl))(rl)
rl.On("List", mock.Anything, spaceID).Return([]*roles.Role{{ID: roleID, SpaceID: spaceID, Description: "Role"}}, nil).Once()
vl1, err := svc.List(ctx, spaceID)
require.NoError(t, err)
vl2, err := svc.List(ctx, spaceID)
require.NoError(t, err)
assert.Same(t, vl1[0], vl2[0], "Ожидается при повторном запросе получение объекта из кэша.")
rl.On("Create", mock.Anything, mock.Anything).Return(&roles.Role{ID: "roleID2", SpaceID: spaceID, Description: "Role2"}, nil).Once()
_, err = svc.Create(ctx, &roles.Role{ID: "roleID2", SpaceID: spaceID, Description: "Role2"})
require.NoError(t, err)
rl.On("List", mock.Anything, spaceID).Return([]*roles.Role{{ID: roleID, SpaceID: spaceID, Description: "Role"}, {ID: "roleID2", SpaceID: spaceID, Description: "Role2"}}, nil).Once()
vl3, err := svc.List(ctx, spaceID)
require.NoError(t, err)
assert.Len(t, vl3, 2, "Ожидает что после создания нового объекта, кеш будет очищен и объекты запрошены заново из сервиса.")
rl.AssertExpectations(t)
})
t.Run("After TTL expired", func(t *testing.T) {
rl := &rsmocks.Roles{}
svc := CachingMiddleware(cache.NewCache(size, ttl))(rl)
rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "Role"}, nil).Once()
v1, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
v2, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
assert.Same(t, v1, v2, "Ожидается получение объекта из кэша.")
time.Sleep(2 * ttl)
rl.On("Get", mock.Anything, spaceID, roleID).Return(&roles.Role{ID: roleID, SpaceID: spaceID, Description: "Role"}, nil).Once()
v3, err := svc.Get(ctx, spaceID, roleID)
require.NoError(t, err)
assert.NotSame(t, v2, v3, "Ожидается что объект был удален из кеша и получен заново из сервиса.")
rl.AssertExpectations(t)
})
})
}