ruby-on-rails - rspec + 应该 : setting up data

标签 ruby-on-rails testing rspec shoulda

我有以下测试。共有三个 it block 。与其他两个不同,第一个不使用 shoulda

如果我不将 before block 与 post :create, product: attrs 一起使用,那么第一个测试将按预期失败。但是,如果我将 before block 放在那里,那么第一个测试会失败,但其他两个会通过。我对产品名称进行了唯一性验证,但这应该不是问题,因为我正在使用工厂序列。

我该怎么办?当同时存在 rspec 和 shoulda 匹配器时,我通常应该如何设置用于测试的数据?

describe "when user logged in" do
  before(:each) do
    login_user #logged in user is available by calling @user
  end

  context "POST create" do
    context "with valid attributes" do
      let!(:profile) { create(:profile, user: @user) }
      let!(:industry) { create(:industry) }
      let!(:attrs) { attributes_for(:product, user_id: @user.id, industry_ids: [ industry.id ]).merge(
          product_features_attributes: [attributes_for(:product_feature)],
          product_competitions_attributes: [attributes_for(:product_competition)],
          product_usecases_attributes: [attributes_for(:product_usecase)]
        ) }

      it "saves the new product in the db" do
        expect{ post :create, product: attrs }.to change{ Product.count }.by(1)
      end

      #If I don't use this the 2 tests below fail. If I use it, then the test above fails.
      # before do
      #   post :create, product: attrs
      # end

      it { is_expected.to redirect_to product_path(Product.last) }
      it { is_expected.to set_flash.to('Product got created!') }
    end
  end
end

工厂

factory :product, class: Product do
  #name { Faker::Commerce.product_name }
  sequence(:name) { |n| "ABC_#{n}" }
  company { Faker::Company.name }
  website { 'https://example.com' }
  oneliner { Faker::Lorem.sentence }
  description { Faker::Lorem.paragraph }
  user
end

最佳答案

你不能两全其美。如果您在 before 中执行您正在测试的方法,则您无法再次执行它以查看它是否更改了 Product 计数。如果您之前不执行它,那么您必须在您的示例中执行它,因此不能使用 is_expected 一种内衬格式。

有多种选择。这是一个将方法的执行合并到所有示例中的方法。

describe "when user logged in" do
  before(:each) do
    login_user #logged in user is available by calling @user
  end

  describe "POST create" do
    subject(:create) { post :create, product: attrs }
    context "with valid attributes" do
      let!(:profile) { create(:profile, user: @user) }
      let!(:industry) { create(:industry) }
      let!(:attrs) { attributes_for(:product, user_id: @user.id, industry_ids: [ industry.id ]).merge(
          product_features_attributes: [attributes_for(:product_feature)],
          product_competitions_attributes: [attributes_for(:product_competition)],
          product_usecases_attributes: [attributes_for(:product_usecase)]
        ) }

      it "saves the new product in the db" do
        expect{ create }.to change{ Product.count }.by(1)
      end

      it("redirects") { expect(create).to redirect_to product_path(Product.last) }
      it("flashes") { expect(create).to set_flash.to('Product got created!') }
    end
  end
end

关于ruby-on-rails - rspec + 应该 : setting up data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36827856/

相关文章:

mysql - ActiveRecord::Relation 包含 ID 为 nil 的对象以及为什么未选择其他数据

angularjs - 配置字段中的颜色和 logColors 有什么区别

ruby-on-rails - Rspec.config 之前(:each) except for specific :types

rspec - 预期 css "title"与 capybara 文本

ruby-on-rails - 更改表的平均分组计算

ruby-on-rails - 如何在 Mongrel 下重启 Rails,无需停止和启动 Mongrel

javascript - Jest : Timer and Promise don't work well.(setTimeout 和异步函数)

Scalatest:如果两个匹配器之一匹配,则测试有效

ruby-on-rails-3 - BDD/TDD (Rails/Rspec) 入门

ruby-on-rails - Rails 3 - lib 未初始化常量 ActionView::CompiledTemplates::STATES