我如何 运行 在 Redis pub/sub 上进行 phpunit 测试?

How do I run a phpunit test on Redis pub/sub?

我正在构建一个消息系统,其中 Redis 在 Laravel 端发布并在节点服务器上订阅。我想使用 PHPUnit 测试 redis pub 方法中存储的内容,但我不知道从哪里开始。

控制器

class MessageController extends Controller
{

    public function store(Conversation $conversation, Request $request)
    {
        $user = Auth::user();

        $message = Message::create([
            'body' => $request->input('message'),
            'conversation_id' => $conversation->id,
            'sender_id' => $user->id,
            'type' => 'user_message'
        ]);
             
        $redis = Redis::connection();
            
        $data = new MessageResource($message);

        $redis->publish('message', $data);

    }
}

当前测试

/** @test */
public function a_user_can_send_a_message()
{
    $this->actingAs($user = User::factory()->create());

    $message = Message::factory()->make(['sender_id' => $user->id]);

    $conversation Conversation::factory()->create();

    $response = $this->json('POST', '/api/message/'. $conversation->id, ['message' => $message->body])
        ->assertStatus(201);
    
    $response->assertJsonStructure([
        'data' => [
            'body',
            'sender',
        ]
    ]);
}

本质上,我想要查看的是消息是否已在 Redis 上发布。我不确定该怎么做,我认为您可能需要在之后清除来自 Redis 的消息,不是吗?

你的测试应该是这样的:

public function test_a_user_can_send_a_message()
{
    $redisSpy = Redis::spy();

    $redisSpy->shouldReceive('connection')->andReturnSelf();

    $this->actingAs($user = User::factory()->create());

    $message = Message::factory()->make(['sender_id' => $user->id]);

    $conversation = Conversation::factory()->create();

    $this->postJson("/api/message/{$conversation->id}", ['message' => $message->body]);

    $this->assertDatabaseCount('messages', 1);

    $redisSpy->shouldHaveReceived('publish')
        ->with('message', new MessageResource(Message::first()));
}

如您所见,我添加了 Redis::spy(); 这将允许“监视”从 Redis 调用的内容。你仍然可以 mock 方法,我们必须这样做,因为你使用 Redis::connect(); 然后 $redis->publish(...),所以我们将 return spyconnect 被调用时,这就是为什么我们做 shouldReceive('connection')->andReturnSelf().

在代码的末尾,我们检查 $redis->publish 是否使用参数 'message' 和包含所需消息的资源调用。两者都必须匹配才能通过此断言,否则您将看到一个模拟错误。