类: RSpec::Mocks::MessageExpectation

继承
Object
  • Object
显示全部
定义在
lib/rspec/mocks/message_expectation.rb

概述

代表单个方法存根或消息期望。这里定义的方法可用于配置其行为。这些方法返回 self,以便它们可以链接在一起形成流畅的接口。

直接已知子类

VerifyingMessageExpectation

配置响应 折叠

限制接收计数 折叠

其他约束 折叠

实例方法详细信息

#and_call_originalnil

注意

这仅适用于部分双重。

告诉对象在接收到消息时委托给原始未修改的方法。

示例

expect(counter).to receive(:increment).and_call_original
original_count = counter.count
counter.increment
expect(counter.count).to eq(original_count + 1)

返回值

  • (nil)

    在此之后不支持进一步链接。

141
142
143
144
145
146
147
148
# File 'lib/rspec/mocks/message_expectation.rb', line 141
def and_call_original
  block = lambda do |original, *args, &b|
    original.call(*args, &b)
  end
  block = block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
  wrap_original(__method__, &block)
end

#and_invoke(first_proc, *procs, &_block) ⇒nil

告诉对象在接收到消息时调用 Proc。如果给定多个值,则第一次接收消息时返回第一个 Proc 的结果,第二次接收消息时返回第二个 Proc 的结果,依此类推。

如果接收消息的次数超过 Proc 的数量,则对于每次后续调用都返回最后一个 Proc 的结果。

示例

allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout })
api.get_foo # => raises ApiTimeout
api.get_foo # => raises ApiTimeout

allow(api).to receive(:get_foo).and_invoke(-> { raise ApiTimeout }, -> { raise ApiTimeout }, -> { :a_foo })
api.get_foo # => raises ApiTimeout
api.get_foo # => raises ApiTimeout
api.get_foo # => :a_foo
api.get_foo # => :a_foo
api.get_foo # => :a_foo
# etc

返回值

  • (nil)

    在此之后不支持进一步链接。

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/rspec/mocks/message_expectation.rb', line 109
def and_invoke(first_proc, *procs, &_block)
  raise_already_invoked_error_if_necessary(__method__)
  if negative?
    raise "`and_invoke` is not supported with negative message expectations"
  end
  if block_given?
    raise ArgumentError, "Implementation blocks aren't supported with `and_invoke`"
  end
  procs.unshift(first_proc)
  if procs.any? { |p| !p.respond_to?(:call) }
    raise ArgumentError, "Arguments to `and_invoke` must be callable."
  end
  @expected_received_count = [@expected_received_count, procs.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least)
  self.terminal_implementation_action = AndInvokeImplementation.new(procs)
  nil
end

#and_raisenil #and_raise(ExceptionClass) ⇒ nil #and_raise(ExceptionClass, message) ⇒ nil #and_raise(exception_instance) ⇒ nil

注意

当您传递异常类时,MessageExpectation 将引发其实例,使用 exception 创建它,如果指定,则传递 message。如果异常类初始化程序需要多个参数,则必须传入实例而不是类,否则此方法将引发 ArgumentError 异常。

告诉对象在接收到消息时引发异常。

示例

allow(car).to receive(:go).and_raise
allow(car).to receive(:go).and_raise(OutOfGas)
allow(car).to receive(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive")
allow(car).to receive(:go).and_raise(OutOfGas.new(2, :oz))

返回值

  • (nil)

    在此之后不支持进一步链接。

186
187
188
189
190
# File 'lib/rspec/mocks/message_expectation.rb', line 186
def and_raise(*args)
  raise_already_invoked_error_if_necessary(__method__)
  self.terminal_implementation_action = Proc.new { raise(*args) }
  nil
end

#and_return(value) ⇒ nil #and_return(first_value, second_value) ⇒ nil

告诉对象在接收到消息时返回值。如果给定多个值,则第一次接收消息时返回第一个值,第二次接收消息时返回第二个值,依此类推。

如果接收消息的次数超过值的数量,则对于每次后续调用都返回最后一个值。

示例

allow(counter).to receive(:count).and_return(1)
counter.count # => 1
counter.count # => 1

allow(counter).to receive(:count).and_return(1,2,3)
counter.count # => 1
counter.count # => 2
counter.count # => 3
counter.count # => 3
counter.count # => 3
# etc

返回值

  • (nil)

    在此之后不支持进一步链接。

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rspec/mocks/message_expectation.rb', line 71
def and_return(first_value, *values, &_block)
  raise_already_invoked_error_if_necessary(__method__)
  if negative?
    raise "`and_return` is not supported with negative message expectations"
  end
  if block_given?
    raise ArgumentError, "Implementation blocks aren't supported with `and_return`"
  end
  values.unshift(first_value)
  @expected_received_count = [@expected_received_count, values.size].max unless ignoring_args? || (@expected_received_count == 0 && @at_least)
  self.terminal_implementation_action = AndReturnImplementation.new(values)
  nil
end

#and_throw(symbol) ⇒ nil #and_throw(symbol, object) ⇒ nil

告诉对象在接收到消息时抛出符号(如果使用该形式,则带有对象)。

示例

allow(car).to receive(:go).and_throw(:out_of_gas)
allow(car).to receive(:go).and_throw(:out_of_gas, :level => 0.1)

返回值

  • (nil)

    在此之后不支持进一步链接。

202
203
204
205
206
# File 'lib/rspec/mocks/message_expectation.rb', line 202
def and_throw(*args)
  raise_already_invoked_error_if_necessary(__method__)
  self.terminal_implementation_action = Proc.new { throw(*args) }
  nil
end

#and_wrap_original(&block) ⇒nil

注意

这仅适用于部分双重。

使用提供的块装饰存根方法。原始未修改的方法与任何方法调用参数一起传递给块,因此您可以委托给它,同时仍然能够更改传递给它的参数和/或更改返回值。

示例

expect(api).to receive(:large_list).and_wrap_original do |original_method, *args, &block|
  original_method.call(*args, &block).first(10)
end

返回值

  • (nil)

    在此之后不支持进一步链接。

162
163
164
# File 'lib/rspec/mocks/message_expectation.rb', line 162
def and_wrap_original(&block)
  wrap_original(__method__, &block)
end

#and_yield(*args) {|@eval_context = Object.new| ... } ⇒MessageExpectation

告诉对象在接收到消息时向块 yield 一个或多个参数。

示例

stream.stub(:open).and_yield(StringIO.new)

Yields

  • (@eval_context = Object.new)

返回值

214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/rspec/mocks/message_expectation.rb', line 214
def and_yield(*args, &block)
  raise_already_invoked_error_if_necessary(__method__)
  yield @eval_context = Object.new if block
  # Initialize args to yield now that it's being used, see also: comment
  # in constructor.
  @args_to_yield ||= []
  @args_to_yield << args
  self.initial_implementation_action = AndYieldImplementation.new(@args_to_yield, @eval_context, @error_generator)
  self
end

#at_least(n, &block) ⇒MessageExpectation

将消息期望限制为至少接收特定次数。

示例

expect(dealer).to receive(:deal_card).at_least(9).times

返回值

249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/rspec/mocks/message_expectation.rb', line 249
def at_least(n, &block)
  raise_already_invoked_error_if_necessary(__method__)
  set_expected_received_count :at_least, n
  if n == 0
    raise "at_least(0) has been removed, use allow(...).to receive(:message) instead"
  end
  self.inner_implementation_action = block
  self
end

#at_most(n, &block) ⇒MessageExpectation

将消息期望限制为最多接收特定次数。

示例

expect(dealer).to receive(:deal_card).at_most(10).times

返回值

268
269
270
271
272
273
# File 'lib/rspec/mocks/message_expectation.rb', line 268
def at_most(n, &block)
  raise_already_invoked_error_if_necessary(__method__)
  self.inner_implementation_action = block
  set_expected_received_count :at_most, n
  self
end

#exactly(n, &block) ⇒MessageExpectation

将消息期望限制为接收特定次数。

示例

expect(dealer).to receive(:deal_card).exactly(10).times

返回值

236
237
238
239
240
241
# File 'lib/rspec/mocks/message_expectation.rb', line 236
def exactly(n, &block)
  raise_already_invoked_error_if_necessary(__method__)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, n
  self
end

#neverMessageExpectation

期望根本不接收消息。

示例

expect(car).to receive(:stop).never

返回值

293
294
295
296
297
# File 'lib/rspec/mocks/message_expectation.rb', line 293
def never
  error_generator.raise_double_negation_error("expect(obj)") if negative?
  @expected_received_count = 0
  self
end

#once(&block) ⇒MessageExpectation

期望消息恰好接收一次。

示例

expect(car).to receive(:go).once

返回值

304
305
306
307
308
# File 'lib/rspec/mocks/message_expectation.rb', line 304
def once(&block)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, 1
  self
end

#ordered(&block) ⇒MessageExpectation

期望消息按特定顺序接收。

示例

expect(api).to receive(:prepare).ordered
expect(api).to receive(:run).ordered
expect(api).to receive(:finish).ordered

返回值

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/rspec/mocks/message_expectation.rb', line 379
def ordered(&block)
  if type == :stub
    RSpec.warning(
      "`allow(...).to receive(..).ordered` is not supported and will " \
      "have no effect, use `and_return(*ordered_values)` instead."
    )
  end
  self.inner_implementation_action = block
  additional_expected_calls.times do
    @order_group.register(self)
  end
  @ordered = true
  self
end

#thrice(&block) ⇒MessageExpectation

期望消息恰好接收三次。

示例

expect(car).to receive(:go).thrice

返回值

326
327
328
329
330
# File 'lib/rspec/mocks/message_expectation.rb', line 326
def thrice(&block)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, 3
  self
end

#times(&block) ⇒MessageExpectation 也称为: time

exactlyat_leastat_most 的语法糖。

示例

expect(dealer).to receive(:deal_card).exactly(10).times
expect(dealer).to receive(:deal_card).at_least(10).times
expect(dealer).to receive(:deal_card).at_most(10).times

返回值

282
283
284
285
# File 'lib/rspec/mocks/message_expectation.rb', line 282
def times(&block)
  self.inner_implementation_action = block
  self
end

#to_sString 也称为: inspect

返回消息期望的良好表示。

返回值

  • (String)

    消息期望的良好表示

396
397
398
399
400
# File 'lib/rspec/mocks/message_expectation.rb', line 396
def to_s
  args_description = error_generator.method_call_args_description(@argument_list_matcher.expected_args, "", "") { true }
  args_description = "(#{args_description})" unless args_description.start_with?("(")
  "#<#{self.class} #{error_generator.intro}.#{message}#{args_description}>"
end

#twice(&block) ⇒MessageExpectation

期望消息恰好接收两次。

示例

expect(car).to receive(:go).twice

返回值

315
316
317
318
319
# File 'lib/rspec/mocks/message_expectation.rb', line 315
def twice(&block)
  self.inner_implementation_action = block
  set_expected_received_count :exactly, 2
  self
end

#with(*args, &block) ⇒MessageExpectation

将存根或消息期望限制为使用特定参数的调用。

对于存根,如果可能使用其他参数接收消息,则应首先存根默认值,然后使用 with 存根或模拟相同消息以将其限制为特定参数。

如果使用不同的参数接收消息,则消息期望将失败。

示例

allow(cart).to receive(:add) { :failure }
allow(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
cart.add(Book.new(:isbn => 1234567890))
# => :failure
cart.add(Book.new(:isbn => 1934356379))
# => :success

expect(cart).to receive(:add).with(Book.new(:isbn => 1934356379)) { :success }
cart.add(Book.new(:isbn => 1234567890))
# => failed expectation
cart.add(Book.new(:isbn => 1934356379))
# => passes

返回值

359
360
361
362
363
364
365
366
367
368
369
# File 'lib/rspec/mocks/message_expectation.rb', line 359
def with(*args, &block)
  raise_already_invoked_error_if_necessary(__method__)
  if args.empty?
    raise ArgumentError,
          "`with` must have at least one argument. Use `no_args` matcher to set the expectation of receiving no arguments."
  end
  self.inner_implementation_action = block
  @argument_list_matcher = ArgumentListMatcher.new(*args)
  self
end