如何使用RSpec测试ActionCable通道?

时间:2016-02-05 15:29:41

标签: ruby-on-rails rspec ruby-on-rails-5 actioncable

我想知道测试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的任何内容。

4 个答案:

答案 0 :(得分:8)

您可能希望等待* https://github.com/rails/rails/pull/23211合并。它添加了ActionCable :: TestCase。一旦合并,期望 rspec-rails 团队尽其所能:https://github.com/rspec/rspec-rails/issues/1606

  

*等待是可选的;你不能在这个“正在进行的工作”中等待自己的工作并找到一个现在可行的解决方案。

答案 1 :(得分:3)

我会安装和配置TCR gem用于录制套接字交互(&#39;它类似于VCR for websockets&#39;)

在你的情况下,这个规范可能看起来像这样......

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

答案 2 :(得分:3)

您可以使用`action-cable-testing` gem。

将此添加到您的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

有关更多信息,请参阅github repo中的自述文件。

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

rspec和test_case都有例子

答案 3 :(得分:0)

现在,Rails 6包含action-cable-test gem

因此无需添加宝石。你可以做

assert_has_stream "chat_1"

或者,使用rspec:

expect(subscription).to have_stream_from("chat_1")