1

我尝试通过 Capybara 在 Mongoid 支持的 Rails 3.2.3 应用程序中使用 Cucumber 运行场景。目的是让当前用户将一本书添加到他的收藏中。

一切正常,但最后一步定义,我检查书籍的数量现在是一,失败了。

但如果我检查应用控制器,大小实际上增加了。实际上,当我reload在步骤定义中发送给用户时,它通过了:

user.reload.books(true).size.should == 1

我担心这种行为一旦投入生产可能会损害我的应用程序。关于如何确保所有测试和应用程序行为一致的任何建议?

更新

我检查了 test.log 以了解发生了什么。调用reload我得到这个查询到 MongoDB:

find({"count"=>"books",
"query"=>{:_id=>{"$in"=>[BSON::ObjectId('4f889b473dffd63235000004')]}},
"fields"=>nil}).limit(-1)

虽然没有重新加载,但我得到了这个:

find({"count"=>"books", "query"=>{:_id=>{"$in"=>[]}}, "fields"=>nil}).limit(-1)

user如果我不重新加载模型,它实际上不会查询,这对我来说没有多大意义。

4

1 回答 1

0

以下对我有用(用实际的 Cucumber 示例更新)

我建立了一个 Rails 项目来测试你的问题,rails 3.2.3,mongoid 2.4.8,mongo 1.6.2,mongodb 2.0.4,cucumber 1.1.9。

以下(关联生成方法)按预期工作,无需刷新:

user.books << book
book.users << user

然后我试图绕过关联,这就是我认为你正在做的事情。

user.push(:book_ids, book.id)
book.push(:user_ids, user.id)

这些 DO 绕过关联,导致不完整(单向而不是双向)引用,但内存和数据库状态是一致的。因此,我在之前的回答中对您遇到的问题的猜测是错误的,不需要刷新,您可能正在做其他事情。请注意,您/我们不想要不完整的引用,请不要直接推送到 Mongoid 引用关系的内部。

您是否使用关联附加“<<”来添加用户或书籍?我目前的结论是,Mongoid 引用的关系作为我测试您的问题的广告而起作用。无需刷新。

这是模型:

class User
  include Mongoid::Document
  field :first_name, type: String
  field :last_name, type: String
  has_and_belongs_to_many :books
end

class Book
  include Mongoid::Document
  field :title, type: String
  field :author, type: String
  has_and_belongs_to_many :users
end

黄瓜功能

Feature: UserAndBook
  Test adding a book to a user_s books

  Scenario: add_book_to_user
    Given starting with no users and no books
    And a new user
    And that the new user has no books
    And a new book
    And add book to user
    Then I can check that the user has a book

黄瓜步骤

require 'test/unit/assertions'
require File.expand_path('../../../test/test_helper', __FILE__)
World(Test::Unit::Assertions)

Given 'starting with no users and no books' do
  User.delete_all
  Book.delete_all
  assert_equal(0, User.count)
  assert_equal(0, Book.count)
end

Given 'a new user' do
  @user = User.create(first_name: 'Gary', last_name: 'Murakami')
end

Given 'that the new user has no books' do
  assert_equal(0, @user.books.count)
end

Given 'a new book' do
  @book = Book.create(title: 'A Tale of Two Cities', author: 'Charles Dickens')
end

Given 'add book to user' do
  @user.books << @book
end

Then 'I can check that the user has a book' do
  assert_equal(1, @user.books.count)
end

我愿意进一步交换信息以帮助解决您的问题。

祝福,

-加里

PS 查看日志,有趣的是 user.books.length 执行的是实际的 db“find count $in”查询,而不是本地数组长度。

上一个答案

你几乎已经回答了你自己的问题。在 Rails 中,每当模型的数据在数据库中发生更改时,您都需要使用 reload 方法,否则您将只查看模型先前加载/实例化/缓存的状态。仅更新一个属性,事情看起来很一致,但关联更加复杂,不一致变得更加明显。

于 2012-04-05T20:54:20.927 回答