2012-12-20 38 views
11
改变

可能重复:
Is it possible for RSpec to expect change in two tables?RSpec的,期望有多个值

it "should create a new Recipe" do 
    expect { click_button submit }.to change(Recipe, :count).by(1) 
end 

这让我检查 '食谱' 模式有一个条目,但我还想检查'成分'模型是否还有一个条目。期望块只能执行一次,因为表单已经提交。

我知道我可以制作另一个'it'块,但我觉得必须有DRYer方式。

+0

这个问题是codereview.stackexchange –

回答

48

我建议通过重新定义的受试者(使用stabby lambdas为了好玩)干燥起来:

describe "recipe creation" do 
    subject { -> { click_button submit } } 
    it { should change(Recipe, :count).by(1) } 
    it { should change(Ingredient, :count).by(1) } 
end 

更新:虽然它可能看起来不那么干的,这些天我可能仍然会继续使用expect语法,因为它的recommended,我通常从should远离,但也许对规格readabi做一些小的更改lity:

describe "recipe creation" do 
    let(:creating_a_recipe) { -> { click_button submit } } 

    it "changes the Recipe count" do 
    expect(creating_a_recipe).to change(Recipe, :count).by(1) 
    end 

    it "changes the Ingredient count" do 
    expect(creating_a_recipe).to change(Ingredient, :count).by(1) 
    end 
end 

注意:你可以在expect使用大括号的RSpec documentation for the change matcher看到。当然,这是正确的,但是标准括号在这个例子中起作用的原因是改变可变状态的代码(包含在creating_a_recipe中)是在作为参数传入expect时被调用的lambda中。

无论如何,在这种情况下,expect(creating_a_recipe)expect { creating_a_recipe }都可以成功使用,并且您使用的任何一个都可以达到个人偏好。

+3

现在问题已经关闭,但为了它,'...} .to {{val1,val2]} .from([old_val1,old_val2])'会工作得很好。 – zakelfassi

+0

请注意,有必要实际调用lambda来发生任何事情。我使用方括号来实现,例如'creating_a_recipe []'。 –

+1

'expect'会调用一个lamba,如果一个被传入。 –

0

你可以抽象成一个辅助方法

def test_creation_of(model) 
    it "should create a new #{model}" do 
    expect { click_button submit }.to change(model.constantize, :count).by(1) 
    end 
end 

但我只想建议,如果你会做这许多车型了这一切。否则它只会使代码更难阅读。如果你这样做,最好把它放入一个规范助手。另外,根据测试中的其他先例,您可以传递一个Const对象而不是一个字符串(正如我在上面的示例中所用的那样)。

然后

it "should create a new Recipe" do 
    test_creation_of('Recipe') 
    test_creation_of('Ingredient') 
end 
+0

为未来的边界:此代码有效。在这种情况下,Downvotes通常不合适 - 您应该反对评论(或者说明为什么此代码无法解决问题)。 –

+0

这是测试模型创建的一个很好的抽象,但是OP询问如何通过一次单击测试创建两个模型。你是对的,它会培养一个更好的社区来撰写评论,而不是简单地下载。我的错。 –

+0

有趣的是,因为已经过了2天,所以在更新答案之前,我不会让我收回我的低估。 –