【问题标题】:Using Rails 5 and minitest, how can I access a record that was created in the test?使用 Rails 5 和 minitest,我如何访问在测试中创建的记录?
【发布时间】:2018-04-21 22:16:51
【问题描述】:

在我将 Note 表切换为使用 UUID 之前,我已经通过了这个测试:

test "SHOULD create note AND redirect to Notes#index(SINCE null folder_id) WHEN only body is provided IF logged in as account:owner" do
  sign_in @user
  assert_difference('@user.account.notes.count') do
    post notes_url(@user.account.hash_id), params: { note: { body: @note_by_user_no_folder.body } }
  end
  assert_redirected_to notes_url(@user.account.hash_id, anchor: Note.last.id)
end

但切换到 UUID 后,出现以下失败错误:

Failure:
NotesControllerTest#test_SHOULD_create_note_AND_redirect_to_Notes#index(SINCE_null_folder_id)_WHEN_only_body_is_provided_IF_logged_in_as_account:owner [/Users/chris/Dropbox/Repositories/keepshelf/test/controllers/notes_controller_test.rb:117]:
Expected response to be a redirect to <http://www.example.com/11111111/notes#9dc409ff-14cc-5f64-8f5f-08e487f583ee> but was a redirect to <http://www.example.com/11111111/notes#34dac6b7-46af-4c5c-bff7-760ffa77edf6>.
Expected "http://www.example.com/11111111/notes#9dc409ff-14cc-5f64-8f5f-08e487f583ee" to be === "http://www.example.com/11111111/notes#34dac6b7-46af-4c5c-bff7-760ffa77edf6".

我认为这是因为 UUID 不遵循命令,所以我在“post notes_url(...”中创建的新注释最终不会成为 Note.last.id 找到的“最后一个”。

如何将锚:设置为record_that_was_just_created.id

【问题讨论】:

  • 您可以尝试使用 created_at 查找最后创建的记录(但在 db 中,它会四舍五入到秒,因此其中一些可能会以相同的时间结束)。或者你可以传入一个 uniq 属性并使用 find_by 作为该属性。
  • 谢谢。做 Note.order(created_at: :desc).last.id 不一致(我假设你描述的原因)。如果无法访问刚刚创建的记录,我不知道如何进行 find_by。
  • 当您在测试中调用post 时,您不知道参数中会包含什么吗?说{ body: "special body" },然后说find_by(body: "special body")
  • 恕我直言,是时候退后一步,考虑一下您的测试可能不正确 :) 无论如何,您不应该依赖增量 ID 来验证结果。更好的测试是检查你正在写的笔记的内容,看看它是否出现在笔记页面上。话虽如此,如果您绝对必须,您可以按created_at 时间戳对笔记进行排序,获取 ID 并从那里获取..

标签: ruby-on-rails ruby activerecord minitest


【解决方案1】:

我想通了。显然有一种方法可以在测试中访问控制器的实例变量,所以我通过将 assert_redirected_to 更改为来让它工作

assert_redirected_to notes_url(@user.account.hash_id, anchor: controller.instance_variable_get(:@note).id)

【讨论】:

    【解决方案2】:

    这里迟到的答案,我很高兴你得到了你需要的结果!

    ... 以防其他人阅读本文以寻找测试实践 ...

    简短的回答是 - 您应该始终知道测试中使用了哪些数据……因为您做到了。最常见的3种方式...

    在你所在的setup方法中

    • 加载 fixture @account = Accounts(:first)(需要 yaml 文件中的匹配条目)
    • 调用 factorybot gem(有关操作方法,请参见thoughtbot 页面)
    • 明确写@account = @user.account.build(field: value, field2: value)

    所以,你的问题得到了字面上的答案 - 对不确定的数据进行测试是不好的做法 - Shaunak 也这么说。

    以上内容可能就足够了——但您的面向细节的测试应该在单元测试中进行——您不会调用 db 并使您的测试成为可能的最慢版本。您的集成级别的东西应该只是测试创建是否成功 - 您已经知道其中的数据有效。

    为了获得最佳体验,您可能希望在 setup 中对上述 3 种方法中的某些内容进行单元测试,并在测试中使用 @account 来测试您将要创建的验证...

    所以单元测试将是......

    setup
      @account = @user.account.build  # avoid hitting db unnecessarily versus create
      @account.field = value
      @account.field2 = value2
    end
    
    def test_details_pass_activerecord_validations
      signin @user
      @account.test_specific_fields = value  # stuff not all the tests use
      assert @account.valid?  # trigger all the activerecord validations, but not db 
    end
    

    从那里您的集成...

    test "SHOULD create note AND redirect to Notes#index(SINCE null folder_id) WHEN only body is provided IF logged in as account:owner" do
      # Your setup method above should have most of the intialization 
      # ... basically @account = @user.account .note would be setup, but not inserted
    
      signin @user
      assert_difference('@user.account.notes.count') do
        post notes_url(@account), params: { note: { body: @account.note.body } }
      end
      assert_redirected_to notes_url(@account, anchor: @account.whatever_field)
    end
    

    【讨论】:

      猜你喜欢
      • 2018-06-20
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多