为什么ruby会返回`true`进行方法调用?

时间:2017-08-02 16:23:53

标签: ruby-on-rails ruby rspec

所以这是一个简短的教程,我在Rspec上发现了w3ii.com: rspec关于rspec助手的解释。这是示例的代码:

class Dog
   attr_reader :good_dog, :has_been_walked

   def initialize(good_or_not)
      @good_dog = good_or_not
      @has_been_walked = false
   end

   def walk_dog
      @has_been_walked = true
   end
end

describe Dog do
   def create_and_walk_dog(good_or_bad)
      Dog.new(good_or_bad).walk_dog
   end

   it 'should be able to create and walk a good dog' do
      dog = create_and_walk_dog(true)

      expect(dog.good_dog).to be true
      expect(dog.has_been_walked).to be true
   end
end

当我运行时,我收到此错误:

  

NoMethodError:未定义的方法'good_dog'表示true:TrueClass
  #./dor.rb:22:in'block< 2 levels>在>'

我无法理解对Dog.new()的调用如何返回true:TrueClass对象而不是简单的狗。

2 个答案:

答案 0 :(得分:3)

那是因为create_and_walk_dog返回walk_dog方法返回

要从create_and_walk_dog方法返回一只狗,您需要像

这样的东西
describe Dog do
   def create_and_walk_dog(good_or_bad)
      dog = Dog.new(good_or_bad)
      dog.walk_dog
      dog
   end

   it 'should be able to create and walk a good dog' do
      dog = create_and_walk_dog(true)

      expect(dog.good_dog).to be true
      expect(dog.has_been_walked).to be true
   end
end

或延长期望区块:

describe Dog do
   it 'should be able to create and walk a good dog' do
      dog = Dog.new(true)

      expect(dog.good_dog).to be true
      expect {
        dog.walk_dog
      }.to change(dog, :has_been_walked).from(false).to true
   end
end

答案 1 :(得分:0)

我认为为了清楚起见,您可以/应该使用RSpec let方法,而不是RSpec文件中包含的完整方法定义。让我的_walk_dog_方法返回自我,就像我在另一个答案中建议的那样,我在这里看到了修复你当前的RSpec实现,但是在你潜在的应用程序的任何其他地方都无法帮助你流动。假设情况狗在50%的时间内随机返回 false 为_dog.walk_dog_或者根本不合作。

class Dog
  attr_reader :good_dog, :has_been_walked

  def initialize(good_or_not)
    @good_dog = good_or_not
    @has_been_walked = false
  end

  # Command to attempt walking a dog.
  # 
  # @api public
  # 
  # @example
  #   good_dog = Dog.new(true)
  #   good_dog.walk_dog # => Will always return true for good dogs.
  #   bad_dog = Dog.new(false)
  #   bad_dog.wal_dog # => 50/50 chance of true or false
  def walk_dog
    return @has_been_walked = true if @good_dog
    [true, false].sample
  end
end

describe Dog do

  let(:good_dog) { Dog.new(true) }

  it 'should always be able to walk a good dog' do
    expect(good_dog.walk_dog).to be true
  end

  it 'should track if the dog has been walked' do
    expect {
      good_dog.walk_dog
    }.to change(dog, :has_been_walked).from(false).to true
  end

end

还有争议,但你应该只是在每个规范中声明一件事,除非你正在击中数据库或做一些相对耗时的事情。

P.S。他们都是好狗布伦特