rspec: 如何测试redis#subscribe代码?

rspec: How to test redis#subscribe code?

给出类似的东西:

class MyClass
  def subscribe
    $redis.subscribe('channel') do |on|
       on.message do |channel, msg|
         Something.create(msg)
       end
    end
  end
end

我如何测试当 MyClass 执行 subscribe 时,它会为它在频道上收到的每条消息 运行 Something.create

虽然这种方法没有使用实际测试,但我会执行以下操作并检查日志。

class MyClass
  def subscribe
    $redis.subscribe('channel') do |on|
       on.message do |channel, msg|
         event = Something.create(msg)
         p event.persisted? ? "success" : "fail"
         p event
       end
    end
  end
end

您拥有的这段代码不太可测试。首先,绝对摆脱这个全局 $redis 变量。相反,在构造函数中接受一个 redis 实例。

class MyClass
  attr_reader :redis

  def initialize(redis)
    @redis = redis
  end

  def subscribe
    redis.subscribe('channel') do |on|
       on.message do |channel, msg|
         Something.create(msg)
       end
    end
  end
end

然后在测试中你可以制作一个你可以完全控制但符合你正在使用的 api 的虚拟 redis。沿着这些线的东西:

class DummyRedis
  def subscribe(&block)
    @block = block
  end

  def trigger_on
    @block.call make_on_message
  end
end


fake_redis = DummyRedis.new

expect {
  mc = MyClass.new(fake_redis)
  mc.subscribe
  fake_redis.trigger_on
}.to change{Something.count}.from(0).to(1)

这种很酷的技术称为依赖注入(或者,正如某些人所说,"passing parameters to constructors")。

好吧,它可以像

一样简单
describe MyClass do 
  it 'should create something' do 
    expect(Something).to receive(:create)
    subject.subscribe

    subject.trigger_message # you should trigger a message somehow
  end
end