Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 理解RSpec中as_null_对象的需要_Ruby_Testing_Rspec_Tdd - Fatal编程技术网

Ruby 理解RSpec中as_null_对象的需要

Ruby 理解RSpec中as_null_对象的需要,ruby,testing,rspec,tdd,Ruby,Testing,Rspec,Tdd,在阅读RSpec手册的过程中,我偶然发现了这个方法。我不理解这本书对为什么需要它的解释: 。。。最简单的方法是告诉双输出只侦听我们告诉它期望的消息,而忽略任何其他消息 但是为什么示例代码会失败呢?在每个示例中调用double('output')时,我们不是为每个示例创建一个新的double对象并向其发送一条消息吗 我想要的是对示例代码失败的原因以及as\u null\u object如何解决这个问题的更深入的解释(比书中的解释) it "sends a welcome messag

在阅读RSpec手册的过程中,我偶然发现了这个方法。我不理解这本书对为什么需要它的解释:

。。。最简单的方法是告诉双输出只侦听我们告诉它期望的消息,而忽略任何其他消息

但是为什么示例代码会失败呢?在每个示例中调用
double('output')
时,我们不是为每个示例创建一个新的double对象并向其发送一条消息吗

我想要的是对示例代码失败的原因以及
as\u null\u object
如何解决这个问题的更深入的解释(比书中的解释)

  it "sends a welcome message" do
    output = double('output')
    game = Game.new(output)
    output.should_receive(:puts).with('Welcome to Codebreaker!')
    game.start
  end

  it "prompts for the first guess" do
    output = double('output')
    game = Game.new(output)
    output.should_receive(:puts).with('Enter guess:')
    game.start
  end
这本书试图在前面的一节中解释错误的原因,但我还是不理解解释

在第一个示例中,我们已经告诉double期望
放置
“欢迎使用Codebreaker!”并且我们已经满足了该要求,但我们只告诉它期望“欢迎使用Codebreaker!”它不知道任何关于“输入猜测”:

类似地,第二个示例中的double期望“enterguess:”但它得到的第一条消息是“欢迎使用Codebreaker”


当您使用
output=double('output')
创建一个双人,然后将其传递到
game.new(output)
中的新游戏时,该双人将接收在codebreaker游戏代码中传递的每条消息。您没有包括它,但是
start
方法有以下代码:

module Codebreaker
  class Game
    ...
      def start
        @output.puts 'Welcome to Codebreaker!'
        @output.puts 'Enter guess:'
      end
  end
end
这里,请记住double
output
已分配给
游戏
initialize
方法中的实例变量
@output
,因此在每个规范中都会使用两条消息调用它,第一条消息是“欢迎使用Codebreaker!”,然后使用“输入猜测:”

如果没有
作为\u null\u对象
输出
double将在接收到预期之外的任何内容时失败,即在第一个规范中,除了“欢迎使用Codebreaker!”之外的任何内容在第二个规范中,除了“输入guess:”以外的任何内容。通过在double上使用
作为\u null\u object
,您可以告诉它坐下来等待并忽略除预期之外的任何内容。这避免了上述问题


希望这能有所帮助。

我同意解释并不十分清楚。这就是我的理解,也许再加上shioyama的回答会让这个点击

当您创建规范时,您是说输出将包括预期的短语,但不是说它将只包括预期的短语。假设你把所有的期望都放在一个例子中,这样就避免了这个错误:

   it "gets expected output" do
     output = double('output')
     game = Game.new(output)
     output.should_receive(:puts).with('Welcome to Codebreaker!')
     output.should_receive(:puts).with('Enter guess:')
     game.start
   end

这会过去的。问题是,如果你以后决定让游戏开始时说“嗨,乔!”,那么游戏就会失败。然后,您必须返回并修复您的规范,而实际上,它已经满足了规范。您需要一种机制,使输出能够对意外的输入做出反应,而无需任何行为。这样,您就可以获得预期的特定输出示例,而不会在出现意外情况时失败。这看起来像是非常基本的编程和单元测试断言,但在RSpec中,它们以您和我都不清楚的方式实现。短语“null object”承载了很多负担,似乎没有描述它在做什么,但它是null object模式()的实现。

谢谢您的提醒。