【问题标题】:rspec: How to test redis#subscribe code?rspec:如何测试 redis#subscribe 代码?
【发布时间】:2015-09-25 12:22:43
【问题描述】:

鉴于类似:

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

【问题讨论】:

  • 为什么要用$redis作为全局变量?
  • 从理论上讲,您有两种方法可以做到这一点:1- 模拟 Redis 对象 2- 测试 msg 是否已发布到频道。
  • Alexey:为了更容易理解代码,在我的真实代码中,它是@store,但是我必须将初始化代码放在示例中,我想有一个简单的使用案例。
  • @moeabdol : mock_redis 不支持 pubsub 功能。

标签: ruby rspec redis publish-subscribe


【解决方案1】:

你有这个代码,它不是很可测试。首先,绝对摆脱这个全局$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)

这种很酷的技术称为依赖注入(或者,正如某些人所说,“将参数传递给构造函数”)。

【讨论】:

  • 我对 DI 了如指掌,我以前经常这样做,但是使用 rspec allow 我发现我只将它用作最后的手段(这里可能就是这种情况),因为我不当有理由让测试更容易时,喜欢增加复杂性。
  • 啊,那好吧。我很快就会删除我的答案:)
  • 嗯,DI 也有其他好处,除了便于测试。最重要的是,减少耦合。
  • 不,我决定这样做,因为这似乎是我的情况下唯一合理的方法。顺便说一句,我是 DI 的忠实粉丝,我只是发现对于简单的用例来说,它往往会使代码库和复杂性增长过快。但有时,这是唯一的测试方法。
  • 嗯,这是一种填空法。 :) 让我看看能不能做点什么
【解决方案2】:

嗯,它可以像

一样简单
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

【讨论】:

  • redis.subscribe 将阻止执行。因此,此代码无效
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多