首页 > 解决方案 > 如何转换 `expect_any_instance_of()`(因为它已被弃用)以便我的载波 rspec 测试仍然通过?

问题描述

从 rspec 文档中,expect_any_instance_of()已被弃用。不过,到目前为止,我还没有找到一种用另一种方法替换该方法的简单方法。到目前为止,我尝试过的一切都失败了,尤其是调用了预期会被嘲笑的方法。

context 'test Foo' do
  before(:each) do
    info = double(
      size: 12345,
      close: true
    )
    allow(Blah).to receive(:open).and_return(info)  # this one works
  end                                                                       

  it 'returns false on failure' do
    # This expect_any_instance_of() works like a charm
    expect_any_instance_of(MyUploader).to receive(:process_with_some_tool).and_return(false)

    uploader = MyUploader.new(create(:my_object, data: nil))

    # These expect()'s fails
    expect(MyUploader).to receive(:process_with_some_tool).and_return(true)
    expect(uploader).to receive(:process_with_some_tool).and_return(true)

    uploader.store!(trigger_data)
  end
end

第一个expect(MyUploader)(使用类名),我也尝试将其放置在before块内。我有点期待它无论如何都会失败,因为对象的类名uploader在运行时看起来像这样(当然,每次运行的数字都会改变):

MyUploader::Uploader47181996911040

但是,我不明白为什么expect(uploader)(所以我刚刚分配的对象)也失败了。既然我依附于我创建的对象,为什么不:process_with_some_tool嘲笑该事件并返回true

我有一个puts "CALLED\n":process_with_some_tool当我使用expect(). 我用的时候看不到expect_any_instance_of()。所以前者不嘲笑任何东西,而后者按预期模拟......

我还试图围绕Method stubs帮助页面转一圈,但同样,我无法让它工作。

所以我的问题是:我们如何转换expect_any_instance_of()它才能真正起作用?

注意:我是 Ruby、Rails、RSpec 和所有这些方面的新手。我怀疑这很容易,但我只是不知道如何使它全部工作......


该实现是专有的,但这是我使用的基本表示:

class MyUploader < CarrierWave::Uploader::Base
  include Inspectable

  version :cleanup do
    process :func1
    process :func2
    process :func3
    after :store, :check_size
  end

  def func1
    # Do work
  end

  def func2
    if info.close
      tmpfile = 'temp_file1.ext'
      successful_processing = process_with_some_tool1(tmpfile)
      log "message 1" unless successful_processing
    end

    if !info.close
      tmpfile = 'temp_file2.ext'
      successful_processing = process_with_some_tool2(tmpfile)
      log "message 2" unless successful_processing
    end
  end

  def func3
    # Do work
  end

  def process_with_some_tool1(tmpfile)
    puts "TOOL1 RUN"
    system %Q{mytool1 -a -b -c "#{tmpfile}"}
  end

  def process_with_some_tool2(tmpfile)
    puts "TOOL2 RUN"
    system %Q{mytool2 -a -b -c "#{tmpfile}"}
  end

  def check_size
    begin
      if size < 100
        raise "Too small"
      end
    rescue => error
      log "some message"
    end
  end
end

这是我所拥有的基本表示。该代码是专有的,所以我不能只是复制粘贴整个内容。

我看到的是"TOOL2 RUN"当我期望那个(和 tool1)因为expect().

请注意,我没有看到store在这里实施。所以它来自基类。


更新:

我看到store!()调用cache()和调用versions!()versions!()实现包括以下初始化函数:

    def build_version(name, options)                                        
      uploader = Class.new(self)                                            
      const_set("Uploader#{uploader.object_id}".gsub('-', '_'), uploader)   
      uploader.version_names += [name]                                      
      ...snip...
    end

正如我们所看到的,这个函数创建了一个新类并将其命名为“Uploader<#id>”,这正是我将 class/object_id 打印到控制台时所看到的。

检查所有 ID,我现在可以看到测试中使用的实际对象是 thisClass.new()创建的对象,而不是我在代码中创建的对象。

build_version方法来自~/.rvm/gems/ruby-2.5.3/gems/carrierwave-0.11.0/lib/carrierwave/uploader/versions.rb. 它是为您的测试缓存文件的上传器功能的一部分。看起来它不仅限于缓存文件......现在我想知道我是否有权访问该缓存对象并被允许附加我的expect()allow()那个版本。我将专门与Carrierwave 实施者核实。他们更有可能找到解决这个问题的办法。

标签: rubyruby-on-rails-4rspeccarrierwaverspec-rails

解决方案


推荐阅读