Last active
January 10, 2022 20:51
-
-
Save tomekw/02f4d9c8b7872da4a2bed4d8422551d7 to your computer and use it in GitHub Desktop.
Unit testing ActionCable channels with RSpec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/channels/hello_channel.rb | |
class HelloChannel < ActionCable::Channel::Base | |
def say_hello(data) | |
times_to_say_hello = data.fetch("times_to_say_hello") | |
hello = "Hello, #{current_profile.name}!" | |
times_to_say_hello.times do | |
ActionCable.server.broadcast(current_profile.id, hello) | |
end | |
end | |
end | |
# spec/channels/hello_channel_spec.rb | |
require "spec_helper" | |
# This is the minimal ActionCable connection stub to make the test pass | |
class TestConnection | |
attr_reader :identifiers, :logger | |
def initialize(identifiers_hash = {}) | |
@identifiers = identifiers_hash.keys | |
@logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(StringIO.new)) | |
# This is an equivalent of providing `identified_by :identifier_key` in ActionCable::Connection::Base subclass | |
identifiers_hash.each do |identifier, value| | |
define_singleton_method(identifier) do | |
value | |
end | |
end | |
end | |
end | |
RSpec.describe HelloChannel do | |
subject(:channel) { described_class.new(connection, {}) } | |
let(:current_profile) { double(id: "1", name: "Bob") } | |
# Connection is `identified_by :current_profile` | |
let(:connection) { TestConnection.new(current_profile: current_profile) } | |
let(:action_cable) { ActionCable.server } | |
# ActionCable dispatches actions by the `action` attribute. | |
# In this test we assume the payload was successfully parsed (it could be a JSON payload, for example). | |
let(:data) do | |
{ | |
"action" => "test_action", | |
"times_to_say_hello" => 3 | |
} | |
end | |
it "broadcasts 'Hello, Bob!' 3 times" do | |
expect(action_cable).to receive(:broadcast).with("1", "Hello, Bob!").exactly(3).times | |
channel.perform_action(data) | |
end | |
end |
Hi. I tried to use this example but the TestConnection stub is raising an error "Undefined method server
for TestConnection"
As @FrankGu mentioned, fixing line 47 makes the spec pass, yay!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I believe the the
action
value in line 47 should besay_hello
instead oftest_action
:)