Как проверить каналы ActionCable с помощью RSpec?

Мне интересно, как тестировать каналы ActionCable.

Скажем, у меня есть следующий канал чата:

class ChatChannel < ApplicationCable::Channel
  def subscribed
    current_user.increment!(:num_of_chats)

    stream_from "chat_#{params[:chat_id]}"
    stream_from "chat_stats_#{params[:chat_id]}"
  end
end

Метод subscribed обновляет db и определяет два потока, которые будут транслироваться по каналу, но детали не очень важны, поскольку мой вопрос является более общим:

  • Как настроить тест для проверки логики, связанной с подпиской на этот канал?

RSpec предоставляет множество вспомогательных методов и различных утилит при тестировании подобных взаимодействий, таких как действие контроллера, но я могу найти что-либо в отношении RSpec и ActionCable.

Ответы

Ответ 1

Вероятно, вы хотите подождать * для https://github.com/rails/rails/pull/23211 для объединения. Он добавляет ActionCable:: TestCase. Как только это объединится, ожидайте, что команда rspec-rails сделает свою часть: https://github.com/rspec/rspec-rails/issues/1606

* Ожидание необязательно; Вы не можете ждать и основывать свою собственную работу над этой "незавершенной работой" и находить решение, которое работает прямо сейчас.

Ответ 2

Я установил и настроил TCR gem для взаимодействия сокетов (например, VCR для веб-сайтов)

Спецификация для этого в вашем случае может выглядеть примерно так:

describe ChatChannel do
  context ".subscribed" do
    it "updates db and defines opens 2 streams for one channel" do
      TCR.use_cassette("subscribed_action") do |cassette|
        # ...
        ChatChannel.subscribed
        expect(cassette).to include "something ..."
      end
    end
  end
end

Ответ 3

Вы можете использовать драгоценный камень `action-cable-testing`.

Добавьте это в свой Gemfile
gem 'action-cable-testing'
Затем запустите $ bundle install

Затем добавьте следующую спецификацию

# spec/channels/chat_channel_spec.rb

require "rails_helper"

RSpec.describe ChatChannel, type: :channel do
  before do
    # initialize connection with identifiers
    stub_connection current_user: current_user
  end

  it "rejects when no room id" do
    subscribe
    expect(subscription).to be_rejected
  end

  it "subscribes to a stream when room id is provided" do
    subscribe(chat_id: 42)

    expect(subscription).to be_confirmed
    expect(streams).to include("chat_42")
    expect(streams).to include("chat_stats_42")
  end
end

Для получения дополнительной информации см. readme в github repo.

https://github.com/palkan/action-cable-testing

Есть примеры как для rspec, так и для test_case