Rspec 方法在(:all)之前存根

Rspec 方法在(:all)之前存根,rspec,rspec-rails,Rspec,Rspec Rails,当我在(:each)之前使用before(:all)时,它可以工作。但是,如果在(:all)之前使用,它将抛出错误作为nil:NilClass的未定义的方法proxy\u。我找不出原因。你能帮帮我吗?提前感谢。before(:all)不受欢迎,但不支持在(:all)before(before)中使用rspec mock的双精度。有关背景信息,请参阅中的参考问题 3.0.0.beta2中提供的rspec模拟的当前主版本将失败,并出现以下错误: require './spec/spec_helper

当我在(:each)之前使用
before(:all)
时,它可以工作。但是,如果在(:all)之前使用
,它将抛出错误作为nil:NilClass的
未定义的方法proxy\u。我找不出原因。你能帮帮我吗?提前感谢。

before(:all)
不受欢迎,但不支持在(:all)
before(
before)中使用rspec mock的双精度。有关背景信息,请参阅中的参考问题

3.0.0.beta2中提供的rspec模拟的当前主版本将失败,并出现以下错误:

require './spec/spec_helper'
require './bank'

describe Bank do
  context "#transfer" do
    before(:all) do
      @customer1 = Customer.new(500)
      customer2 = Customer.new(0)
      @customer1.stub(:my_money).and_return(1000)
      customer2.stub(:my_money).and_return(0)
      @transfer_message = Bank.new.transfer(@customer1, customer2, 2000)
    end 

    it "should return insufficient balance if transferred amount is greater than balance" do
      expect(@transfer_message).to eq("Insufficient funds")
    end 

    it "calls my_money" do
      expect(@customer1).to have_received(:my_money)
    end 
  end 
end
以前的版本将在存根点为…
错误生成
未定义的方法代理。\

这应该可以:

The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported.

晚会迟到了?是的,但我不介意从我发现的东西中拿出我自己的一分钱。我在尝试在
RSpec.configure
块中存根请求时遇到了类似的错误,因此存根将仅对我将
config.around(:each,option)
选项传递给的示例可用

因此,这意味着我使用的存根超出了单个示例的范围,
RSpec::Mocks
!。解决方法是在上下文中使用临时范围

你有吗

require "rspec/mocks/standalone"
before(:all) do

我不确定它是否与使用一样规范/最佳实践,但我发现,通过在
挂钩周围使用
,而不是在
之前使用
,我能够动态地将
之前的
块(以及类似的块)注入到
示例组
,从而使它们与我的测试一起运行:

例子 现在,如果我们假设我们的测试已经在
之前
之后以及
测试本身内部打印了一些日志,那么我们的输出如下所示:

# spec/spec_helper.rb
RSpec.configure do |config|
  # ..snip..
  config.include RequestForgerySpecHelper, type: :feature
  # ..snip..
end

# spec/support/request_forgery_spec_helper.rb
module RequestForgerySpecHelper
  def self.included(base)
    base.around(:all) do |ex|
      puts "around all start"

      ex.example_group.prepend_before do
        puts "around all inside prepend_before"
      end

      ex.example_group.append_after do
        puts "around all inside append_after"
      end

      ex.run

      puts "around all end"
    end
  end
end
因为我们现在动态地将
之前的
钩子注入到与测试相同的上下文中,所以我们不再看到以下错误:

require './spec/spec_helper'
require './bank'

describe Bank do
  context "#transfer" do
    before(:all) do
      @customer1 = Customer.new(500)
      customer2 = Customer.new(0)
      @customer1.stub(:my_money).and_return(1000)
      customer2.stub(:my_money).and_return(0)
      @transfer_message = Bank.new.transfer(@customer1, customer2, 2000)
    end 

    it "should return insufficient balance if transferred amount is greater than balance" do
      expect(@transfer_message).to eq("Insufficient funds")
    end 

    it "calls my_money" do
      expect(@customer1).to have_received(:my_money)
    end 
  end 
end
before
在示例(例如
it
块)内或在示例范围内运行的构造(例如
before
let
等)中不可用。它仅适用于示例组(例如
descripe
context
块)

深入 提供给
around
钩子的
ex
参数是的一个实例,它通过属性访问该实例

RSpec::Core::Example
允许我们通过方法访问与此测试关联的
RSpec::Core::ExampleGroup

RSpec::Core::ExampleGroup
允许我们访问DSL/方法,允许我们在
/
之后动态定义
之前
/
之后
/块,而不触发示例中的
不可用错误;正如我们在pry中列出的方法所看到的:

around all start
around all inside prepend_before
inside spec file before
inside spec file test
inside spec file after
around all inside append_after
around all end

正如我所记得的,
before(:all)
被去除润滑并替换为
before do…
也更合适的方法是不使用变量,您可以使用
let
。若您有nil:NilClass,这意味着rspec并没有在数据库中创建客户记录(它可以通过调用
let!(:object){action}
)作为解析器)诸如此类。出于好奇,你能告诉我为什么他们不支持之前的rspec3吗?查看github发行版中的链接,你会得到一些背景。这是令人惊讶的,可能应该在核心IMO中,例如,“当使用标记示例的子集时,这应该很好,并且应该在临时范围内执行”。小心。重新运行测试用例时,这开始给我带来更多错误:
SQLite3::ConstraintException:UNIQUE constraint
。也许添加一个关于standalone的解释会更好。通过在我的测试文件顶部设置一个
调试器
解决了这个问题,在使用
model.destroy\u all
触发时删除了所有模型记录,还必须使用
Base.connection.execute
删除sql序列。
ls RSpec::Core::ExampleGroup
# RSpec::Core::Hooks#methods: after  append_after  append_before  around  before  hooks  prepend_after  prepend_before
# RSpec::Core::MemoizedHelpers::ClassMethods#methods: let  let!  subject  subject!
# RSpec::Core::ExampleGroup.methods:
#  add_example           currently_executing_a_context_hook?  define_nested_shared_group_method  describe                            ensure_example_groups_are_configured  fcontext   ffeature              fit                    fspecify                              include_examples       location                 parent_groups   run                       scenario   specify                          superclass_metadata    update_inherited_metadata  xexample   xspecify
#  before_context_ivars  declaration_locations                delegate_to_metadata               described_class                     example                               fdescribe  file_path             focus                  id                                    it                     metadata                 pending         run_after_context_hooks   set_it_up  store_before_context_ivars       top_level?             with_replaced_metadata     xfeature
#  children              define_example_group_method          descendant_filtered_examples       description                         example_group                         feature    filtered_examples     for_filtered_examples  idempotently_define_singleton_method  it_behaves_like        next_runnable_index_for  remove_example  run_before_context_hooks  set_ivars  subclass                         top_level_description  xcontext                   xit
#  context               define_example_method                descendants                        each_instance_variable_for_example  examples                              fexample   find_and_eval_shared  fscenario              include_context                       it_should_behave_like  ordering_strategy        reset_memoized  run_examples              skip       superclass_before_context_ivars  traverse_tree_until    xdescribe                  xscenario