store: add mock store
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
295
store/mock/mock_test.go
Normal file
295
store/mock/mock_test.go
Normal file
@@ -0,0 +1,295 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.unistack.org/micro/v4/store"
|
||||
)
|
||||
|
||||
func TestStore(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := NewStore()
|
||||
|
||||
// Test Write with expectation
|
||||
s.ExpectWrite("test_key").WithValue("test_value")
|
||||
err := s.Write(ctx, "test_key", "test_value")
|
||||
if err != nil {
|
||||
t.Fatalf("Write failed: %v", err)
|
||||
}
|
||||
|
||||
// Test Read with expectation
|
||||
s.ExpectRead("test_key").WithValue("test_value")
|
||||
var value interface{}
|
||||
err = s.Read(ctx, "test_key", &value)
|
||||
if err != nil {
|
||||
t.Fatalf("Read failed: %v", err)
|
||||
}
|
||||
if value != "test_value" {
|
||||
t.Fatalf("Expected 'test_value', got %v", value)
|
||||
}
|
||||
|
||||
// Test Read with string
|
||||
s.ExpectRead("test_key")
|
||||
var strValue string
|
||||
err = s.Read(ctx, "test_key", &strValue)
|
||||
if err != nil {
|
||||
t.Fatalf("Read string failed: %v", err)
|
||||
}
|
||||
if strValue != "test_value" {
|
||||
t.Fatalf("Expected 'test_value', got %s", strValue)
|
||||
}
|
||||
|
||||
// Test Write and Read integer with TTL
|
||||
s.ExpectWrite("int_key").WithValue(42).WithTTL(5 * time.Second)
|
||||
err = s.Write(ctx, "int_key", 42, store.WriteTTL(5*time.Second))
|
||||
if err != nil {
|
||||
t.Fatalf("Write int failed: %v", err)
|
||||
}
|
||||
|
||||
s.ExpectRead("int_key")
|
||||
var intValue int
|
||||
err = s.Read(ctx, "int_key", &intValue)
|
||||
if err != nil {
|
||||
t.Fatalf("Read int failed: %v", err)
|
||||
}
|
||||
if intValue != 42 {
|
||||
t.Fatalf("Expected 42, got %d", intValue)
|
||||
}
|
||||
|
||||
// Test Exists with expectation
|
||||
s.ExpectExists("test_key")
|
||||
err = s.Exists(ctx, "test_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Exists failed: %v", err)
|
||||
}
|
||||
|
||||
// Test List with expectation
|
||||
s.ExpectList().WillReturn("test_key", "another_key")
|
||||
keys, err := s.List(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("List failed: %v", err)
|
||||
}
|
||||
if len(keys) != 2 {
|
||||
t.Fatalf("Expected 2 keys, got %d", len(keys))
|
||||
}
|
||||
|
||||
// Test Delete with expectation
|
||||
s.ExpectDelete("test_key")
|
||||
err = s.Delete(ctx, "test_key")
|
||||
if err != nil {
|
||||
t.Fatalf("Delete failed: %v", err)
|
||||
}
|
||||
|
||||
// Test that deleted key doesn't exist
|
||||
s.ExpectExists("test_key").WillReturnError(store.ErrNotFound)
|
||||
err = s.Exists(ctx, "test_key")
|
||||
if err == nil {
|
||||
t.Fatalf("Expected store.ErrNotFound after delete")
|
||||
}
|
||||
|
||||
// Test error handling
|
||||
s.ExpectExists("nonexistent").WillReturnError(store.ErrNotFound)
|
||||
err = s.Exists(ctx, "nonexistent")
|
||||
if err != store.ErrNotFound {
|
||||
t.Fatalf("Expected store.ErrNotFound, got %v", err)
|
||||
}
|
||||
|
||||
// Verify all expectations were met
|
||||
if err := s.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("Expectations not met: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreFastForward(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := NewStore()
|
||||
|
||||
// Write with TTL
|
||||
s.ExpectWrite("ttl_key").WithValue("ttl_value").WithTTL(100 * time.Millisecond)
|
||||
err := s.Write(ctx, "ttl_key", "ttl_value", store.WriteTTL(100*time.Millisecond))
|
||||
if err != nil {
|
||||
t.Fatalf("Write with TTL failed: %v", err)
|
||||
}
|
||||
|
||||
// Check key exists before TTL expires
|
||||
s.ExpectRead("ttl_key")
|
||||
var value string
|
||||
err = s.Read(ctx, "ttl_key", &value)
|
||||
if err != nil {
|
||||
t.Fatalf("Read before TTL failed: %v", err)
|
||||
}
|
||||
if value != "ttl_value" {
|
||||
t.Fatalf("Expected 'ttl_value', got %s", value)
|
||||
}
|
||||
|
||||
// Fast forward by 50ms - key should still exist
|
||||
s.FastForward(50 * time.Millisecond)
|
||||
|
||||
s.ExpectRead("ttl_key")
|
||||
err = s.Read(ctx, "ttl_key", &value)
|
||||
if err != nil {
|
||||
t.Fatalf("Read after 50ms fast forward failed: %v", err)
|
||||
}
|
||||
if value != "ttl_value" {
|
||||
t.Fatalf("Expected 'ttl_value' after 50ms, got %s", value)
|
||||
}
|
||||
|
||||
// Fast forward by another 60ms (total 110ms) - key should expire
|
||||
s.FastForward(60 * time.Millisecond)
|
||||
|
||||
s.ExpectRead("ttl_key").WillReturnError(store.ErrNotFound)
|
||||
err = s.Read(ctx, "ttl_key", &value)
|
||||
if err != store.ErrNotFound {
|
||||
t.Fatalf("Expected store.ErrNotFound after TTL, got %v", err)
|
||||
}
|
||||
|
||||
// Test FastForward on already expired keys
|
||||
s.ExpectWrite("ttl_key2").WithValue("ttl_value2").WithTTL(10 * time.Millisecond)
|
||||
err = s.Write(ctx, "ttl_key2", "ttl_value2", store.WriteTTL(10*time.Millisecond))
|
||||
if err != nil {
|
||||
t.Fatalf("Write with TTL failed: %v", err)
|
||||
}
|
||||
|
||||
// Fast forward by 20ms - key should expire immediately
|
||||
s.FastForward(20 * time.Millisecond)
|
||||
|
||||
s.ExpectRead("ttl_key2").WillReturnError(store.ErrNotFound)
|
||||
err = s.Read(ctx, "ttl_key2", &value)
|
||||
if err != store.ErrNotFound {
|
||||
t.Fatalf("Expected store.ErrNotFound after immediate expiration, got %v", err)
|
||||
}
|
||||
|
||||
if err := s.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("Expectations not met: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreWithOptions(t *testing.T) {
|
||||
s := NewStore(store.Name("test_mock"), store.Namespace("test_ns"))
|
||||
|
||||
if s.Name() != "test_mock" {
|
||||
t.Fatalf("Expected name 'test_mock', got %s", s.Name())
|
||||
}
|
||||
|
||||
opts := s.Options()
|
||||
if opts.Namespace != "test_ns" {
|
||||
t.Fatalf("Expected namespace 'test_ns', got %s", opts.Namespace)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatcher(t *testing.T) {
|
||||
watcher := NewWatcher()
|
||||
|
||||
// Test Stop
|
||||
watcher.Stop()
|
||||
|
||||
// Test Next after stop
|
||||
_, err := watcher.Next()
|
||||
if err != store.ErrWatcherStopped {
|
||||
t.Fatalf("Expected store.ErrWatcherStopped, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreHealth(t *testing.T) {
|
||||
s := NewStore()
|
||||
|
||||
if !s.Live() {
|
||||
t.Fatal("Expected Live() to return true")
|
||||
}
|
||||
|
||||
if !s.Ready() {
|
||||
t.Fatal("Expected Ready() to return true")
|
||||
}
|
||||
|
||||
if !s.Health() {
|
||||
t.Fatal("Expected Health() to return true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreConnectDisconnect(t *testing.T) {
|
||||
s := NewStore()
|
||||
|
||||
err := s.Connect(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Connect failed: %v", err)
|
||||
}
|
||||
|
||||
err = s.Disconnect(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Disconnect failed: %v", err)
|
||||
}
|
||||
|
||||
// Test error propagation
|
||||
s.ExpectWrite("test_key").WillReturnError(store.ErrNotConnected)
|
||||
err = s.Write(context.Background(), "test_key", "value")
|
||||
if err != store.ErrNotConnected {
|
||||
t.Fatalf("Expected store.ErrNotConnected, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreTTL(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := NewStore()
|
||||
|
||||
// Test Write with TTL
|
||||
s.ExpectWrite("ttl_key").WithValue("ttl_value").WithTTL(100 * time.Millisecond)
|
||||
err := s.Write(ctx, "ttl_key", "ttl_value", store.WriteTTL(100*time.Millisecond))
|
||||
if err != nil {
|
||||
t.Fatalf("Write with TTL failed: %v", err)
|
||||
}
|
||||
|
||||
// Read before TTL expires
|
||||
s.ExpectRead("ttl_key")
|
||||
var value string
|
||||
err = s.Read(ctx, "ttl_key", &value)
|
||||
if err != nil {
|
||||
t.Fatalf("Read before TTL failed: %v", err)
|
||||
}
|
||||
if value != "ttl_value" {
|
||||
t.Fatalf("Expected 'ttl_value', got %s", value)
|
||||
}
|
||||
|
||||
// Wait for TTL to expire
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
|
||||
// Read after TTL expires should return ErrNotFound
|
||||
s.ExpectRead("ttl_key").WillReturnError(store.ErrNotFound)
|
||||
err = s.Read(ctx, "ttl_key", &value)
|
||||
if err != store.ErrNotFound {
|
||||
t.Fatalf("Expected store.ErrNotFound after TTL, got %v", err)
|
||||
}
|
||||
|
||||
if err := s.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("Expectations not met: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreExpectedOperations(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := NewStore()
|
||||
|
||||
// Test expected operations with Times
|
||||
s.ExpectWrite("once_key").Times(1)
|
||||
s.ExpectWrite("twice_key").Times(2)
|
||||
|
||||
err := s.Write(ctx, "once_key", "value1")
|
||||
if err != nil {
|
||||
t.Fatalf("Write failed: %v", err)
|
||||
}
|
||||
|
||||
err = s.Write(ctx, "twice_key", "value2")
|
||||
if err != nil {
|
||||
t.Fatalf("Write failed: %v", err)
|
||||
}
|
||||
|
||||
err = s.Write(ctx, "twice_key", "value3")
|
||||
if err != nil {
|
||||
t.Fatalf("Write failed: %v", err)
|
||||
}
|
||||
|
||||
if err := s.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("Expectations not met: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user