模块:RSpec::Core::MemoizedHelpers::ClassMethods
- 包含于
- ExampleGroup
- 定义于
- lib/rspec/core/memoized_helpers.rb
概述
此模块扩展到 ExampleGroup,使这些方法可以在示例组块中调用。您可以将其视为类似于类宏。
实例方法摘要 折叠
-
#let(name, &block) ⇒ void
生成一个方法,该方法的返回值在第一次调用后被记忆。
-
#let!(name, &block) ⇒ void
与
let
相同,只是块由一个隐式的before
钩子调用。 -
#subject(name = nil, &block) ⇒ void
为一个示例组声明一个
subject
,然后可以使用expect
和is_expected
包裹它,使其成为在一个简洁的单行示例中进行期望的目标。 -
#subject!(name = nil, &block) ⇒ void
与
subject
相同,只是块由一个隐式的before
钩子调用。
实例方法详细信息
#let(name, &block) ⇒void
let
可以在任何给定的示例组中适度使用(1、2 或可能 3 个声明)时提高可读性,但过度使用会导致可读性迅速下降。YMMV。
let
可以配置为线程安全或不安全。如果它是线程安全的,访问该值的时间会更长。如果它不是线程安全的,它可能会在生成单独线程的示例中以令人惊讶的方式表现。在 RSpec.configure
上指定此选项。
因为 let
旨在创建在每个示例之间重置的状态,而 before(:context)
旨在设置在示例组中的所有示例之间共享的状态,所以 let
不打算在 before(:context)
钩子中使用。
生成一个方法,该方法的返回值在第一次调用后被记忆。这对于减少在示例之间分配相同局部变量的值的重复很有用。
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/rspec/core/memoized_helpers.rb', line 306 def let(name, &block) # We have to pass the block directly to `define_method` to # allow it to use method constructs like `super` and `return`. raise "#let or #subject called without a block" if block.nil? # A list of reserved words that can't be used as a name for a memoized helper # Matches for both symbols and passed strings if [:initialize, :to_s].include?(name.to_sym) raise ArgumentError, "#let or #subject called with reserved name `#{name}`" end our_module = MemoizedHelpers.module_for(self) # If we have a module clash in our helper module # then we need to remove it to prevent a warning. # # Note we do not check ancestor modules (see: `instance_methods(false)`) # as we can override them. if our_module.instance_methods(false).include?(name) our_module.__send__(:remove_method, name) end our_module.__send__(:define_method, name, &block) # If we have a module clash in the example module # then we need to remove it to prevent a warning. # # Note we do not check ancestor modules (see: `instance_methods(false)`) # as we can override them. if instance_methods(false).include?(name) remove_method(name) end # Apply the memoization. The method has been defined in an ancestor # module so we can use `super` here to get the value. if block.arity == 1 define_method(name) { __memoized.fetch_or_store(name) { super(RSpec.current_example, &nil) } } else define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } } end end |
#let!(name, &block) ⇒void
与 let
相同,只是块由一个隐式的 before
钩子调用。这具有设置状态和提供对该状态的记忆引用的双重目的。
400 401 402 403 |
# File 'lib/rspec/core/memoized_helpers.rb', line 400 def let!(name, &block) let(name, &block) before { __send__(name) } end |
#subject(name = nil, &block) ⇒void
subject
可以配置为线程安全或不安全。如果它是线程安全的,访问该值的时间会更长。如果它不是线程安全的,它可能会在生成单独线程的示例中以令人惊讶的方式表现。在 RSpec.configure
上指定此选项。
为一个示例组声明一个 subject
,然后可以使用 expect
和 is_expected
包裹它,使其成为在一个简洁的单行示例中进行期望的目标。
给定一个 name
,定义一个具有该名称的方法,该方法返回 subject
。这允许您声明一次主题,并在单行代码中隐式地访问它,以及使用揭示意图的名称显式地访问它。
当给定一个 name
时,在块中调用 super
不受支持。
444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/rspec/core/memoized_helpers.rb', line 444 def subject(name=nil, &block) if name let(name, &block) alias_method :subject, name self::NamedSubjectPreventSuper.__send__(:define_method, name) do raise NotImplementedError, "`super` in named subjects is not supported" end else let(:subject, &block) end end |
#subject!(name = nil, &block) ⇒void
与 subject
相同,只是块由一个隐式的 before
钩子调用。这具有设置状态和提供对该状态的记忆引用的双重目的。
510 511 512 513 |
# File 'lib/rspec/core/memoized_helpers.rb', line 510 def subject!(name=nil, &block) subject(name, &block) before { subject } end |