我正在研究控制器rspec,我开始讨厌RSpec,因为它与如何构建测试的不一致。应该有一种方法可以做一件事。我希望听到你说我做错了所以我可以学到它应该如何,但我读的越多,我就越混乱。
让我们忘记should
,只关注新的expect
语法并采用这个简单的支架:
describe "foo" do
before do
@foo = create(:foo)
# _A_
end
# _B_
end
我在_A_
和_B_
标记了2个位置。比以delete
动作为例。对于成功背景的delete
操作最常见的期望是:
因此,对第一期望的测试可以是:
_B_: it { expect{delete :destroy, id @foo}.to change(Foo, :count).by(-1)
但要测试第二个期望,将delete
移到before
部分会很好:
_A_: delete :destroy, id: @foo
_B_: it { expect(response).to redirect_to some_url }
必须先运行 delete
才能使用expect(response)
。
与第三名类似:
_A_: delete :destroy, id: @foo
_B_: it { expect(flash[:notice]).to_not be_nil }
it { expect(flash[:error]).to be_nil }
那么如何将1st和2nd和3rd放入一个看起来很清晰的describe
区块?
答案 0 :(得分:1)
describe "delete" do
before(:each) do
@foo = Foo.create
end
it "should delete from the database" do
expect(delete :destroy, id: @foo).to change(Foo, :count).by(-1)
end
context do
before(:each) do
delete :destroy, id: @foo
end
it "should redirect" do
expect(response).to redirect_to some_url
end
it "should set the flash" do
expect(flash[:notice]).to_not be_nil
expect(flash[:error]).to be_nil
end
end
end
是的,删除操作会出现两次。测试代码通常很难干。恕我直言,你不应该在编写规格时牺牲清晰度以节省空间。
应该有一种方法可以做一件事。
当然,我们可以采用最佳做法,但这并不意味着如果有其他令人信服的理由,所有规范都需要以相同的方式编写。
答案 1 :(得分:1)
你可以把它们放在三个不同的测试中:
describe "foo" do
before(:each) do
@foo = create(:foo)
end
it 'removes something from database' do
expect{delete :destroy, id @foo}.to change(Foo, :count).by(-1)
end
it 'redirects to some page' do
delete :destroy, id: @foo
expect(response).to redirect_to some_url
end
it 'shows some flash[:notice]' do
delete :destroy, id: @foo
expect(flash[:notice]).to_not be_nil
expect(flash[:error]).to be_nil
end
end