In this post
Previously, developers encountered a significant challenge verifying if streams ceased operation correctly. This issue often led to the creation of intricate workarounds or the omission of proper testing.
The Old Way #
Here’s an example:
assert_not ActionCable.server.pubsub.redis_connection_for_subscriptions.subscribed_to?("messages")
This code works but isn’t straightforward to update.
The New Solution #
The next release after 7.1, Rails 7.2, introduces assert_has_no_stream and assert_has_no_stream_for. These new methods simplify the testing of stopped streams.
assert_has_no_stream "messages"
assert_has_no_stream_for User.find(42)
With these new assertion methods, you can straightforwardly express your test goals. This simplicity and clarity strengthen your tests and make them easier to maintain, giving you confidence in the reliability of your code.
Rails 7.2 and later #
The methods are not in any Rails 7.1.x release. They first shipped in Rails 7.2.0, where the Action Cable changelog credits Sebastian Pöll and Junichi Sato. If assert_has_no_stream raises NoMethodError in your test, check your Rails version first.
A full test #
Here is a channel that starts a stream on subscribe and stops it when the user leaves:
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from "messages"
end
def leave
stop_stream_from "messages"
end
end
And the test:
class ChatChannelTest < ActionCable::Channel::TestCase
test "stops streaming when the user leaves" do
subscribe
assert_has_stream "messages"
perform :leave
assert_has_no_stream "messages"
end
end
assert_has_no_stream_for works the same way for a stream started with stream_for and stopped with stop_stream_for. You pass the object, such as a user, and Rails builds the stream name from it.
On Rails 8.1 both versions behave the same way: if the stream is still running, the assertion fails with Stream messages has been started.
Assert the stream started first #
assert_has_no_stream only checks that the stream isn’t in the list right now. It also passes when the channel never started the stream at all, for example after someone renames "messages" in subscribed. That is why the test above calls assert_has_stream before perform :leave. Without that line, a broken subscribed method would still give you a green test.




