带有Factory的Rspec和模型中的虚拟属性不起作用?

时间:2011-03-05 21:41:07

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

我正在使用Rspec和工厂女孩来设置我的测试。我有一个用户工厂,然后我正在使用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

为什么?

2 个答案:

答案 0 :(得分:2)

原始代码中的问题是,除了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

答案 1 :(得分:-1)

我通过将if结构更改为if..elsif来解决此问题。

我猜这显然是返回值,然后另一个如果检查是弄乱的东西。不确定为什么会这样,但是当我这样做时它就起作用了。