我不确定它是否像使用RSpec::Mocks.with_temporary_scope 的@El'Magnifico's answer 一样规范/最佳实践,但我发现通过使用around 挂钩而不是before,我能够动态注入@987654331 @ 块(和类似的)进入example_group,导致它们与我的测试一起运行:
示例
# 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
现在,如果我们假设我们的测试已经打印了一些日志 before、after 和 test 本身,我们的输出如下所示:
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 挂钩动态注入到与测试相同的上下文中,所以我们不再看到以下错误:
before 在示例(例如 it 块)或在示例范围内运行的构造(例如 before、let 等)中不可用。它仅适用于示例组(例如 describe 或 context 块)
深入研究
提供给around 挂钩的ex 参数是RSpec::Core::Example::Procsy 的一个实例,它允许通过example 属性访问RSpec::Core::Example 实例。
RSpec::Core::Example 让我们可以通过example_group 方法访问与此测试关联的RSpec::Core::ExampleGroup。
RSpec::Core::ExampleGroup 允许我们访问 DSL/方法,允许我们动态定义 before/after/let/etc 块,而不会触发 not available from within an example 错误;我们可以通过列出 pry 中的方法看到:
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