如何通过Rspec

时间:2018-08-09 10:23:35

标签: ruby-on-rails redis rspec-rails

我们有一个Lockable问题,它允许通过Redis进行锁定

module Lockable
  extend ActiveSupport::Concern

  def redis_lock(key, options = {})
    Redis::Lock.new(
      key,
      expiration: options[:expiration] || 15,
      timeout: options[:timeout] || 0.1
    ).lock { yield if block_given? }
  end
end

我们在Controller方法中使用它来确保并发请求得到正确处理。

def create
  redis_lock(<generated_key>, timeout: 15) do
    # perform_operation
  end

  render json: <data>, status: :ok
end

测试此操作时,我想测试是否已将正确的generated_key发送到Redis来启动锁定。

我为Redis :: Lock设置了一个期望值,但是总会返回false,大概是因为创建请求是在请求中间而不是在请求结束时发送的。

expect(Redis::Lock).to receive(:create).once

测试结构:

context 'return status ok' do
       When do
          post :create, params: {
            <params>
          }
        end
        Then {
          expect(Redis::Lock).to receive(:create).once
          response.ok?
        }
   end
end

由于在方法调用结束时已清除了锁定,因此我无法检查redis中的密钥作为测试。

This answer建议设置一个与Lockable的结构匹配的伪类,以模拟相同的行为,但是我如何为此编写测试?我们拥有的方法未返回任何值进行验证。

2 个答案:

答案 0 :(得分:1)

根据您提供的代码,我相信您只是设置了错误的测试:

expect(Redis::Lock).to receive(:create).once

这希望Redis::Lock类收到一个create的调用,但是您正在控制器中调用create

您在redis_lock方法中所做的 正在初始化Redis::Lock实例并在其上调用lock。我认为这是您应该测试的:

expect_any_instance_of(Redis::Lock).to receive(:lock).once

实施如下所示:

describe 'Lockable' do
  describe '#redis_lock' do
    subject { lockable.redis_lock(key, options) }

    # you gotta set this
    let(:lockable) { xyz }
    let(:key) { xyz } 
    let(:options) { x: 'x', y: 'y' }

    it 'calls Redis::Lock.new with correct arguments' do 
      expect(Redis::Lock).to receive(:new).with(key: key, options: options)
      subject
    end

    it 'calls #lock on the created Redis::Lock instance' do
      expect_any_instance_of(Redis::Lock).to receive(:lock).once
      subject
    end
  end
end

答案 1 :(得分:0)

这是使用Rspec间谍对The Champ进行的修改,消除了any_instances_of之类的编码异味

Sub SiteSignal()

Dim folderPath As String
Dim Filename As Range
folderPath = "C:\Users\RobEi\Documents\MWAM_Eisenrich\Client_Data\Sacramento\Sacramento_Flow_Pressure"
Filename = ("A2:A29")

End Sub