Ruby on rails 如何在rspec中保持在上下文之间填充数据库?

Ruby on rails 如何在rspec中保持在上下文之间填充数据库?,ruby-on-rails,rspec,Ruby On Rails,Rspec,我刚刚开始使用Rails,我正在为带有RSpec的Todo list应用程序编写一些单元测试。我已经编写并运行了RESTAPI,但现在我似乎无法通过测试找出一个问题。以下是规格: require 'rails_helper' describe "Lists API" do context "from start" do it 'is empty' do get "/lists" expect(response).to be_success exp

我刚刚开始使用Rails,我正在为带有RSpec的Todo list应用程序编写一些单元测试。我已经编写并运行了RESTAPI,但现在我似乎无法通过测试找出一个问题。以下是规格:

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
块的数据库都被清空了。对吗?是否有任何方法可以为每个
描述
创建一个新的数据库,但不能为每个
清空数据库?

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

你可能想考虑的是,通过行动和端点来打破你的规范,比如:

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

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

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

你可能想考虑的是,通过行动和端点来打破你的规范,比如:

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

原因: 在块之间保存对象会使您面临两次发布到
/列表
并导致一次发布失败的问题。在这种情况下,POST
it
块将失败,而GET
it
块将失败,因为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
(用于创建两个获取的记录) 及

这样,如果GET或POST被破坏,您将知道问题的真正原因


最后,如果您仍然想测试更真实的用户流,请考虑编写一个大的<强>集成测试。以下是和。

如果您想测试控制器,最好编写相互独立的
it

原因: 在块之间保存对象会使您面临两次发布到
/列表
并导致一次发布失败的问题。在这种情况下,POST
it
块将失败,而GET
it
块将失败,因为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
(用于创建两个获取的记录) 及

这样,如果GET或POST被破坏,您将知道问题的真正原因

最后,如果您仍然想测试更真实的用户流,请考虑编写一个大的<强>集成测试。这是和