Dennis Hackethal
Dennis Hackethal

Reputation: 14285

Assert Redis publication

I am writing a spec for an after_create callback. The spec looks like this:

it 'broadcasts creation' do
  message = Message.create(body: 'foo')
  expect(Redis.any_instance).to have_received(:publish)
end

My Message model looks like this:

class Message < ActiveRecord::Base
  after_create -> { publish(:create) }

  private

  def publish(name)
    Redis.new.publish(
      self.class.inferred_channel_name,
      json(action)
    )

    Redis.new.publish(
      inferred_channel_name_for_single_record,
      json(action)
    )

    puts 'published!'
  end
end

I know that the callback runs because I am printing 'published' at the end, and I have verified that Redis indeed publishes something twice.

Nonetheless, my spec fails with the following message:

1) Message Methods #entangle without options broadcasts creation
 Failure/Error: expect(Redis.any_instance).to have_received(:publish)
   unstubbed, expected exactly once, not yet invoked: #<AnyInstance:Redis>.publish(any_parameters)
 # ./spec/models/message_spec.rb:20:in `block (5 levels) in <top (required)>'

I am using bourne with mocha to use the have_received matcher.

How can I get this test to pass?

Upvotes: 0

Views: 457

Answers (2)

Jordan Allan
Jordan Allan

Reputation: 4486

Create a mock for Redis and stub out the class and instance methods — new and publish, respectively.

it "broadcasts creation" do
  redis = stub_redis

  Message.create(body: "foo")

  expect(redis).to have_received(:publish).twice
end

def stub_redis
  mock("redis").tap do |redis|
    redis.stubs(:publish)
    Redis.stubs(:new).returns(redis)
  end
end

Upvotes: 2

messanjah
messanjah

Reputation: 9278

You could try using the expect_any_instance_of mock.

it 'broadcasts creation' do
  expect(Redis.any_instance).to receive(:publish).twice
  message = Message.create(body: 'foo')
end

https://www.relishapp.com/rspec/rspec-mocks/v/3-2/docs/working-with-legacy-code/any-instance

Upvotes: 1

Related Questions