Как я могу протестировать каналы 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 обновляет базу данных и определяет два потока, которые будут транслироваться по каналу, но подробности не очень важны, так как мой вопрос более общий:

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

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


person Dani    schedule 05.02.2016    source источник


Ответы (4)


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

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

person Leonel Galán    schedule 08.11.2016

Вы можете использовать гем 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.

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

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

person zhisme    schedule 31.01.2018

Я бы установил и настроил гем TCR для записи взаимодействия с сокетами ("это как видеомагнитофон для веб-сокетов")

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

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
person MilesStanfield    schedule 05.02.2016
comment
Это очень хорошая идея, спасибо, но (и поправьте меня, если я ошибаюсь) использование VCR (и аналогично TCR) имеет смысл, когда вы хотите заглушить внешние HTTP-запросы (например, если действие моего контроллера вызывает внешний вызов), но здесь это не так - здесь я просто хочу вызвать свои собственные внутренние методы. Но еще раз - это хорошая идея, и я попробую. - person Dani; 06.02.2016
comment
Дэни, ты нашел решение? Если да, не могли бы вы указать репо, которое я мог бы проверить? - person Sean Magyar; 30.09.2016
comment
Эй, @SzilardMagyar, ты нашел какое-нибудь решение? - person t s; 15.03.2018

Теперь в Rails 6 включен гем action-cable-test.

Так что нет необходимости добавлять драгоценный камень. Вы можете сделать либо

assert_has_stream "chat_1"

или, с rspec:

expect(subscription).to have_stream_from("chat_1") 
person Tabare    schedule 11.12.2020