miniredis

repository·master·Indexed 25 days ago

https://github.com/alicebob/miniredis

A pure Go implementation of a Redis server designed for unit testing. It provides an in-memory, lightweight replacement for Redis with a real TCP interface, allowing developers to test Redis-dependent code without an external installation. It includes a direct access API to manipulate the database without the network stack, tools for managing TTLs and time simulation via FastForward, and support for a wide range of Redis commands across strings, hashes, lists, sets, sorted sets, streams, and HyperLogLog.

Tokens
5.1K
Snippets
3
Records
42
Agent score
85%

What's inside miniredis

  1. Control randomness with Seed()

    master

    Miniredis uses math/rand's global RNG by default. To ensure deterministic behavior in tests involving randomness, call m.Seed(seed) to provide a specific seed. This affects commands that rely on randomness, such as:

    • RANDOMKEY
    • SPOP
    • SRANDMEMBER
  2. Install and use miniredis/v2

    master

    Miniredis is a pure Go Redis test server designed for Go unittests. It provides an in-memory Redis replacement with a real TCP interface, allowing you to test Redis-dependent code without external dependencies or complex integration tests.

    To use it, import the v2 package:

    import "github.com/alicebob/miniredis/v2"
    import "github.com/alicebob/miniredis/v2"
  3. Manage TTLs and time in miniredis

    master

    In miniredis, TTLs (Time To Live) do not decrease automatically. To simulate the passage of time and trigger key expiration, use the following methods:

    • m.FastForward(d): Decrements all TTLs by the duration d. Any keys with a TTL $\le 0$ after this operation are removed.
    • m.SetTime(t): Sets the base time for EXPIREAT and PEXPIREAT conversions and sets the value returned by the Redis TIME command. Defaults to time.Now().
    • m.TTL(key): Returns the remaining TTL of a key as a time.Duration. Returns 0 if no TTL is set.
  4. Initialize a Miniredis Server

    master
    You can create a new TCP server using NewServer(addr string). To create a server with TLS support, use NewServerTLS(addr string, cfg *tls.Config). Use .Close() to shut down the server and wait for all connected clients to finish.
  5. Start a Miniredis server

    master

    You can start a Miniredis server in several ways depending on your use case:

    1. For testing with testing.T: Use RunT(t). This automatically handles server shutdown via t.Cleanup() when the test finishes.
    2. Manual management: Use Run() to start a server and manually call Close() when finished.
    3. TLS support: Use RunTLS(cfg) for a TLS-enabled server.
    4. Specific address: Use StartAddr(addr) to listen on a specific address (e.g., "127.0.0.1:6379").
  6. Run a miniredis server in a test

    master

    Use miniredis.RunT(t) to start a miniredis server that is automatically cleaned up when the test finishes. You can then use the server's address (s.Addr()) to connect your application via a standard Redis client (like redigo or go-redis).

    Because the server lives in the same process, you can also use the miniredis instance directly to inspect or set values for assertions, bypassing the network stack.

    func TestSomething(t *testing.T) {
    	s := miniredis.RunT(t)
    
    	// Optionally set some keys your code expects:
    	s.Set("foo", "bar")
    	s.HSet("some", "other", "key")
    
    	// Run your code and see if it behaves. 
    	// Example using redigo:
    	c, err := redis.Dial("tcp", s.Addr())
    	_, err = c.Do("SET", "foo", "bar")
    
    	// Optionally check values in redis...
    	if got, err := s.Get("foo"); err != nil || got != "bar" {
    		t.Error("'foo' has the wrong value")
    	}
    	// ... or use a helper for that:
    	s.CheckGet(t, "foo", "bar")
    
    	// TTL and expiration:
    	s.Set("foo", "bar")
    	s.SetTTL("foo", 10*time.Second)
    	s.FastForward(11 * time.Second)
    	if s.Exists("foo") {
    		t.Fatal("'foo' should not have existed anymore")
    	}
    }
  7. Reference: Implemented Redis Commands

    master

    Miniredis implements a wide range of Redis commands across several categories. Note that some commands are only partially implemented (e.g., DUMP, RESTORE, INFO, XINFO).

    Command Groups:

    • Connection: AUTH, ECHO, HELLO, PING, SELECT, SWAPDB, QUIT
    • Key: COPY, DEL, DUMP, EXISTS, EXPIRE, EXPIREAT, EXPIRETIME, KEYS, MOVE, PERSIST, PEXPIRE, PEXPIREAT, PEXPIRETIME, PTTL, RANDOMKEY, RENAME, RENAMENX, RESTORE, SCAN, TOUCH, TTL, TYPE, UNLINK, WAIT
    • Transactions: DISCARD, EXEC, MULTI, UNWATCH, WATCH
    • Server: DBSIZE, FLUSHALL, FLUSHDB, TIME, COMMAND, INFO
    • String keys: APPEND, BITCOUNT, BITOP, BITPOS, DECR, DECRBY, DELEX, GET, GETBIT, GETDEL, GETEX, GETRANGE, GETSET, INCR, INCRBY, INCRBYFLOAT, MGET, MSET, MSETNX, PSETEX, SET, SETBIT, SETEX, SETNX, SETRANGE, STRLEN
    • Hash keys: HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HMGET, HMSET, HRANDFIELD, HSET, HSETNX, HSTRLEN, HVALS, HSCAN
    • List keys: BLPOP, BRPOP, BRPOPLPUSH, LINDEX, LINSERT, LLEN, LPOP, LPUSH, LPUSHX, LRANGE, LREM, LSET, LTRIM, RPOP, RPOPLPUSH, RPUSH, RPUSHX, LMOVE, BLMOVE
    • Pub/Sub: PSUBSCRIBE, PUBLISH, PUBSUB, PUNSUBSCRIBE, SUBSCRIBE, UNSUBSCRIBE
    • Set keys: SADD, SCARD, SDIFF, SDIFFSTORE, SINTER, SINTERSTORE, SINTERCARD, SISMEMBER, SMEMBERS, SMISMEMBER, SMOVE, SPOP, SRANDMEMBER, SREM, SSCAN, SUNION, SUNIONSTORE
    • Sorted Set keys: ZADD, ZCARD, ZCOUNT, ZINCRBY, ZINTER, ZINTERSTORE, ZLEXCOUNT, ZPOPMIN, ZPOPMAX, ZRANDMEMBER, ZRANGE, ZRANGEBYLEX, ZRANGEBYSCORE, ZRANK, ZREM, ZREMRANGEBYLEX, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, ZREVRANGEBYSCORE, ZREVRANK, ZSCORE, ZUNION, ZUNIONSTORE, ZSCAN
    • Stream keys: XACK, XADD, XAUTOCLAIM, XCLAIM, XDEL, XGROUP CREATE, XGROUP CREATECONSUMER, XGROUP DESTROY, XGROUP DELCONSUMER, XINFO STREAM, XINFO GROUPS, XINFO CONSUMERS, XLEN, XRANGE, XREAD, XREADGROUP, XREVRANGE, XPENDING, XTRIM
    • Scripting: EVAL, EVALSHA, SCRIPT LOAD, SCRIPT EXISTS, SCRIPT FLUSH
    • GEO: GEOADD, GEODIST, GEOPOS, GEORADIUS, GEORADIUS_RO, GEORADIUSBYMEMBER, GEORADIUSBYMEMBER_RO
    • Cluster: CLUSTER SLOTS, CLUSTER KEYSLOT, CLUSTER NODES, CLUSTER SHARDS
    • HyperLogLog: PFADD, PFCOUNT, PFMERGE
  8. Manage Miniredis databases and keys directly

    master

    Miniredis allows you to manipulate data directly without a Redis client by accessing its internal RedisDB instances.

    • Access a DB: Use DB(id) to get a pointer to a specific database.
    • Select a DB: Use Select(id) to change the currently selected database for direct commands.
    • Direct commands: You can call methods like Get(key) or Set(key, value) directly on the Miniredis or RedisDB instances.