如何在 rspec 中的上下文之间填充数据库?



我刚刚开始使用Rails,我正在使用RSpec为Todo列表应用程序编写一些单元测试。我已经编写并运行了 REST API,但现在我似乎无法找出测试的问题。这是规格:

require 'rails_helper'
describe "Lists API" do
context "from start" do
it 'is empty' do
get "/lists"
expect(response).to be_success
expect(json.size).to eq(0) 
end
it 'can create Lists' do  
post "/lists", :list => {:title => "First List", :status => "Unstarted"}
expect(response).to be_success
post "/lists", :list => {:title => "Second List", :status => "Unstarted"}
expect(response).to be_success
#lines only here to show the problem only exists in a different test block
get "/lists"
expect(response).to be_success
expect(json.size).to eq(2) 
end
end
context "once populated" do
it 'can view created lists' do
get "/lists"
expect(response).to be_success
expect(json.size).to eq(2)
end
end

end

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

Failures:
1) Lists API once populated can view created lists
Failure/Error: expect(json.size).to eq(2)
expected: 2
got: 0
(compared using ==)

似乎每个it块的数据库都被清空了。这是对的吗?有没有办法为每个describe都有一个新的数据库,但不为每个it清空它?

是的,rspec 将独立处理每个示例(it块)。

您可能需要考虑的一件事是按操作和端点分解您的规范,例如:

describe 'Lists API' do
describe 'GET lists' do
context 'when lists empty' do
before(:each) do
get '/lists'
end
it 'responds with success'
it 'json response is empty'
end
context 'when lists present' do
let!(:list) { List.create(title: 'First List', status: 'Unstarted') }
before(:each) do
get '/lists'
end
it 'responds with success'
it 'json response is present'
end
end
describe 'POST lists' do
it 'can create lists'
end
end

这样,您可以更好地隔离和组织正在测试的内容。实际上,您要测试的是可以成功创建列表并成功获取/呈现列表(空列表和列表项)。

如果你想测试你的控制器,你最好编写it彼此独立的块。

为什么:在块之间保存对象会让您面临两次发布到/lists并且一个发布失败的问题。在这种情况下,您的 POSTit块将失败,而您的 GETit块将失败,因为 GET 依赖于 POST 才能成功。这令人困惑,因为您的GET操作可能没有任何问题,但是无论如何它的测试都会失败。

改进:为控制器中的每个操作设置隔离测试,例如:

describe 'GET /lists' do
before do
List.create(title: 'first list', status: 'Unstarted')
List.create(title: 'second list', status: 'Unstarted')
end
it 'renders all lists' do
get '/lists'
expect(response).to be_success
expect(json.length).to eq(2)
end
end

(之前用于创建两个提取的记录) 和

describe 'POST /lists' do
it 'can create Lists' do  
post "/lists", :list => {:title => "First List", :status => "Unstarted"}
expect(response).to be_success
expect(List.count).to eq(1)
end
end

这样,如果GET或POST损坏,您将知道真正导致问题的原因。

最后,如果仍想测试更真实的用户流,请考虑编写一个大型集成测试。以下是 Rails 文档集成信息和 RSpec 的控制器集成信息。

最新更新