-
Notifications
You must be signed in to change notification settings - Fork 77
Open
Description
Summary
The HSet method in RedisMock passes a JavaScript object to ioredis's hset(), which ioredis flattens to variadic HSET key f1 v1 f2 v2. This fails on Windows where redis-memory-server uses Redis 3.0.503 (variadic HSET requires Redis 4.0+).
Environment
- OS: Windows 11
- Node.js: v22.x
- redis-memory-server: downloads Redis 3.0.503 on Windows
- Package:
@devvit/redistest mocks
Steps to Reproduce
- Use
RedisMockfrom@devvit/redis/teston Windows - Call
redisMock.plugin.HSet()with multiple field-value pairs - Error occurs
Actual Error
ReplyError: ERR wrong number of arguments for 'hset' command
Reproduction Test (Vitest)
Click to expand test code
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { Redis } from 'ioredis';
import { RedisMemoryServer } from 'redis-memory-server';
import { RedisMock } from '@devvit/redis/test';
describe('HSet Bug Verification', () => {
let redisServer: RedisMemoryServer;
let redisConn: Redis;
let redisMock: RedisMock;
beforeAll(async () => {
redisServer = new RedisMemoryServer();
const host = await redisServer.getHost();
const port = await redisServer.getPort();
redisConn = new Redis({ host, port });
redisMock = new RedisMock(redisConn, 'test');
});
afterAll(async () => {
await redisConn?.quit();
await redisServer?.stop();
});
it('fails HSet with multiple fields on Redis 3.x (Windows)', async () => {
const result = await redisMock.plugin.HSet({
key: 'mykey',
fv: [
{ field: 'field1', value: 'value1' },
{ field: 'field2', value: 'value2' },
],
});
expect(result.value).toBeGreaterThanOrEqual(0);
});
});Root Cause
packages/redis/src/test/mocks/RedisMock.ts (lines 244-253)
HSet passes an object to ioredis:
const v = await this._store.conn.hset(this._makeKey(request.key, request.scope), map);ioredis converts this to variadic args, but Redis 3.x only supports HSET key field value (single pair).
Evidence
MSet (lines 468-478) in the same file correctly uses the flattened spread pattern:
const flat: string[] = [];
for (const { key, value } of request.kv) {
flat.push(this._makeKey(key, request.scope), value);
}
await this._store.conn.mset(...flat);I understand the mock is experimental. Sharing in case it helps improve the test mocks.
Metadata
Metadata
Assignees
Labels
No labels