【问题标题】:Rspec assigns fails on adding more codeRspec 分配在添加更多代码时失败
【发布时间】:2014-11-04 01:29:18
【问题描述】:

控制器:测试失败,如果:

 def index
    @products = Product.all
    @products.present? ? @no_products_found = "" : @no_products_found = "No Products available."
 end

失败消息: 预期:2 得到:0

   (compared using ==)

Rspec:

it "assigns products" do
  get :index
  FactoryGirl.create(:product, name: "product 1")
  FactoryGirl.create(:product, name: "product 2")
  expect(assigns(:products).size).to eq(2)
end

如果我将操作更改为:

 def index
    @products = Product.all
 end

PS:刚接触 Rails。感谢您的意见。

【问题讨论】:

  • 您从 RSpec 得到的确切失败消息是什么?
  • 预期:2 得到:0(使用 == 比较)
  • 你在清理你的数据库吗?我本来希望FactoryGirl 行在get :index 行之前。

标签: ruby-on-rails ruby rspec


【解决方案1】:

您需要在执行get 之前调用FactoryGirl.create。自然,在提出请求之前,记录必须存在。

it "assigns products" do
  FactoryGirl.create(:product, name: "product 1")
  FactoryGirl.create(:product, name: "product 2")
  get :index
  expect(assigns(:products).size).to eq(2)
end

虽然我个人会让规范更明确一点:

it "assigns products" do
  get :index
    products = [
      FactoryGirl.create(:product, name: "product 1"),
      FactoryGirl.create(:product, name: "product 2")
    ]
    expect(assigns(:products)).to eq(products)
  end
end

那么你的控制器动作还有另一个问题。三元条件运算符应谨慎使用,在这种情况下,我强烈建议不要使用它,因为它会妨碍可读性。这一行:

@products.present? ? @no_products_found = "" : @no_products_found = "No Products available."

应该写成

@no_products_found = @products.present? ? "" : "No Products available."

甚至

@no_products_found = if @products.present?
                       ""
                     else
                       "No Products available."
                     end

再次,我个人不希望用这种简单的视图逻辑来搞乱我的控制器操作。可能它只在一个地方使用,所以我的解决方案将完全驻留在视图层中:

<% if @products.present? %>
  <% @products.each do |product| %>
    <!-- Render products -->
  <% end %>
<% else %>
  No products available.
<% end %>

【讨论】:

  • 哇,谢谢!这很有帮助。
  • 一个稍微偏离主题的问题 - 如果我在视图中添加逻辑,我将如何测试页面是否显示“没有可用的产品”。或不。我尝试了 should_have_content ,但没有按预期工作
  • 您可以对渲染的主体进行断言,例如expect(response.body).to include('No results found')。您可能还想查看 capybara 的功能规格。这些测试会在后台启动一个真实的 Web 浏览器来模拟用户交互。它们非常适合端到端测试,但我喜欢只关注一些核心功能,因为它们往往会变慢。
  • 没错,我刚刚读到为内容视图创建测试并不常见。您可以假设 html 将显示内容。但是,如果有人必须添加测试,那么使用助手来显示这种东西。
【解决方案2】:

那是因为您在调用 index 方法后创建产品。将规范更改为:

it "assigns products" do
  FactoryGirl.create(:product, name: "product 1")
  FactoryGirl.create(:product, name: "product 2")
  # created products above and then make call to index:
  get :index
  expect(assigns(:products).size).to eq(2)
end

【讨论】:

  • 甜蜜,我刚刚想通了,正要发布答案。但是,为什么它会在第一种情况下通过?
  • @AdRoiT :很抱歉,我在您的帖子中没有看到任何其他案例。你错过了写它吗?
  • 当我定义 index def index @products = Product.all end 时运行相同的测试
  • 不,伙计,这与此无关,实际上,它会第二次起作用,因为旧产品(上次创建)在下次调用中已经存在,如果它不会起作用你会在运行规范之前使用 dbcleaner 来清理数据库。 :)
  • 是的,这是有道理的。谢谢。感谢您的时间。
猜你喜欢
  • 2023-04-06
  • 1970-01-01
  • 2017-08-19
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多