如何使用PHPUnit测试Laravel中Redis pub/sub的消息发布功能?
测试Redis publish逻辑的两种实现方案
方案1:使用Facade Mock做单元测试(推荐,无需真实Redis连接)
该方案适合验证代码逻辑是否正确触发了publish调用,不需要依赖真实Redis服务,执行速度最快。
Laravel的Redis门面支持Mock替换,你可以直接预期publish方法会被调用,以及调用参数是否符合预期。
修改后的测试代码如下:
/** @test */ public function a_user_can_send_a_message_and_publish_to_redis() { $this->actingAs($user = User::factory()->create()); $conversation = Conversation::factory()->create(); $messageBody = 'test message content'; // Mock Redis 门面,预期publish调用 Redis::shouldReceive('connection') ->once() ->andReturnSelf(); // 让connection返回自身实例,承接后续publish调用 Redis::shouldReceive('publish') ->once() ->with('message', \Mockery::on(function ($publishedData) use ($messageBody, $user) { // 验证发布的内容是否符合预期 $data = json_decode($publishedData, true); return $data['body'] === $messageBody && $data['sender']['id'] === $user->id; })); $response = $this->json('POST', '/api/message/'. $conversation->id, ['message' => $messageBody]) ->assertStatus(201); $response->assertJsonStructure([ 'data' => [ 'body', 'sender', ] ]); }
注意:你原测试代码中
$conversation Conversation::factory()->create()一行缺少等于号,需要修正为$conversation = Conversation::factory()->create()。
方案2:集成测试(真实连接Redis验证发布结果)
如果需要端到端验证真实发布逻辑,你可以给测试环境单独配置Redis数据库,避免污染开发环境数据:
- 在
phpunit.xml中添加环境变量,指定测试用Redis库:
<env name="REDIS_DB" value="1"/>
- 测试代码中提前订阅频道,捕获发布的消息做验证:
/** @test */ public function published_message_content_matches_expected() { $this->actingAs($user = User::factory()->create()); $conversation = Conversation::factory()->create(); $messageBody = 'test message content'; $publishedData = null; // 启动订阅捕获消息 $redis = Redis::connection(); $redis->subscribe(['message'], function ($message) use (&$publishedData, $redis) { $publishedData = $message; $redis->unsubscribe(['message']); // 收到消息后取消订阅 }); // 执行请求触发publish $this->json('POST', '/api/message/'. $conversation->id, ['message' => $messageBody]) ->assertStatus(201); // 验证发布内容 $data = json_decode($publishedData, true); $this->assertEquals($messageBody, $data['body']); $this->assertEquals($user->id, $data['sender']['id']); }
关于Redis数据清理的说明
- 如果你使用第一种Mock方案,没有真实写入Redis,完全不需要清理数据。
- 如果你使用第二种集成测试方案:Redis的Pub/Sub消息是无状态的,没有订阅者接收的消息会直接丢弃,不会持久化存储在Redis中,默认不会产生残留数据。如果担心测试过程中产生其他Redis缓存数据,可以在测试基类的
tearDown方法中添加Redis::flushdb()清空当前测试用的Redis库即可。
内容的提问来源于stack exchange,提问作者Kyle Corbin Hurst
相关产品推荐
相关产品推荐

