【问题标题】:Rspec with a Factory and a virtual attribute from a model does not work?具有工厂和模型虚拟属性的 Rspec 不起作用?
【发布时间】:2011-03-05 21:41:07
【问题描述】:

我正在使用 Rspec 和 factory girl 来设置我的测试。我有一个用户工厂,然后我正在使用 rspec 进行测试。

在一个名为 GameEngine::Formulas 的模块中,我有一个虚拟属性(实际上 hp 已经是我的模型,它在这里被覆盖):

def hp
    ((self[:hp] * 5) * (self.level + 1)) if self.first_class == 'Fighter'
    ((self[:hp] * 4) * (self.level + 1)) if self.first_class == 'Ranger'
    ((self[:hp] * 2) * (self.level + 1)) if self.first_class == 'Magician'
end 

当我删除这个虚拟属性时,测试工作正常。但如果我把它留在这里,我明白了:

 Failure/Error: let(:user) { Factory(:user) }
 ActiveRecord::RecordInvalid:
   Validation failed: Hp can't be blank

工厂:

Factory.define :user do |f|
    f.sequence(:username) { |n| "test#{n}" }
    f.password "1234567890"
    f.sequence(:email) { |n| "test#{n}@test.com" }
    f.first_class 'Ranger'
    f.hp 10000
    f.strength 100
    f.magic 100
    f.dexterity 100
    f.accuracy 10
    f.armor 20
    f.level 1
end

为什么会这样?

【问题讨论】:

  • 你的工厂是什么样子的?
  • 我添加了工厂。我实际上通过更改 ifs 结构 thanx 解决了这个问题。

标签: ruby-on-rails rspec factory-bot


【解决方案1】:

原始代码中的问题是它返回nil,除非first_class == 'Magician'。如果条件为假,则带有尾随条件的语句返回 nil,例如

> 1 + 1 if true
# => 2

> 1 + 1 if false
# => nil

每次调用都会执行所有三个测试,因此前两个的结果会被后续的测试所掩盖。

你可以用 case 语句重写它:

  def hp
    case first_class
    when 'Fighter'
      ((self[:hp] * 5) * (level + 1))
    when 'Ranger'
      ((self[:hp] * 4) * (level + 1))
    when 'Magician'
      ((self[:hp] * 2) * (level + 1))
    end
  end

【讨论】:

    【解决方案2】:

    我通过将 if 结构更改为 if..elsif 解决了这个问题。

    我猜想显式返回值然后再进行另一个 if 检查会搞砸事情。不知道为什么会这样,但是当我这样做时它起作用了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-15
      • 2018-01-10
      • 1970-01-01
      • 2018-04-09
      • 1970-01-01
      • 2015-12-26
      相关资源
      最近更新 更多