【问题标题】:ControllerTest error, Couldn't find Transaction with 'id'=ControllerTest 错误,找不到带有 'id'= 的事务
【发布时间】:2015-07-18 12:34:30
【问题描述】:

我的控制器的显示操作未通过单元测试。我的 ControllerTest 出现错误。这是我从“rake test”得到的错误:

> ERROR["test_should_get_show", TransactionsControllerTest, 2015-07-18
> 00:30:18 -0400]  test_should_get_show#TransactionsControllerTest
> (1437193818.29s) ActiveRecord::RecordNotFound:        
> ActiveRecord::RecordNotFound: Couldn't find Transaction with 'id'=
>             app/controllers/transactions_controller.rb:21:in `show'
>             test/controllers/transactions_controller_test.rb:6:in `block in <class:TransactionsControllerTest>'
>         app/controllers/transactions_controller.rb:21:in `show'
>         test/controllers/transactions_controller_test.rb:6:in `block in <class:TransactionsControllerTest>'
> 
>   5/5:
> [=======================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00
> 
> Finished in 0.24993s 5 tests, 4 assertions, 0 failures, 1 errors, 0
> skips

尽管有这个错误,当我使用这个 url 时,视图在浏览器中成功生成了页面: http://localhost:3000/transactions/1

所以,某处有错误。它没有失败。

transactions_controller.rb

class TransactionsController < ApplicationController

  def new
   @transaction = Transaction.new
  end

  def create
    @transaction = Transaction.new(transaction_params)
    if @transaction.save
      # Handle a successful save.
    else
      render 'new'
    end
  end

  def index
    @transactions = Transaction.all
  end

  def show
    @transaction = Transaction.find(params[:id])      #this is row 21
  end

    private
      def transaction_params
        params.require(:transaction).permit(:company, :month, :account_code, :description, :transaction_amount)
      end
end

transaction_controller_test.rb

require 'test_helper'

class TransactionsControllerTest < ActionController::TestCase
  test "should get show" do
    transaction = Transaction.create
    get :show, id: transaction.id          #this is row 6
    assert_response :success 
  end

end

以下夹具是由 rails 自动生成的。我是 Rails 新手,不得不承认我不太了解固定装置。

transactions.yml

one:
  company: MyString
  month: 2015-06-19
  account_code: MyString
  description: MyString
  transaction_amount: 1.5

two:
  company: MyString
  month: 2015-06-19
  account_code: MyString
  description: MyString
  transaction_amount: 1.5

在我的路由文件中,我将根设置为索引操作。我计划通过 url http://localhost:3000/transactions/1 访问 show 操作,并且(如上所述)它确实有效。

routes.rb

Rails.application.routes.draw do
  root            'transactions#index'
  resources       :transactions
end

transaction.rb

class Transaction < ActiveRecord::Base
    validates :month, presence: true 
    validates :account_code, presence: true
end

transaction_test.rb

require 'test_helper'

class TransactionTest < ActiveSupport::TestCase

    def setup
        #@transaction = transactions(:one)
    @transaction = Transaction.new(company: "Inc", month: Date.new(2015,6,15).to_s, 
                                    account_code: "80-32100-12-1201-60010", 
                                    description: "Salaries & Wages - Histo Gross 1", transaction_amount: 100000)
    end

    test "should be valid" do
        assert @transaction.valid?
    end

    test "month should be present" do
    @transaction.month = "     "
    assert_not @transaction.valid?
  end

    test "account_code should be present" do
    @transaction.account_code = "     "
    assert_not @transaction.valid?
  end

  test "month cannot be a string" do      #not sure if this is worth anything at all
    @transaction.month = "xxxxxxxxxxxx"
    assert_not @transaction.valid?
  end


end

Rails 自动生成的测试(在我修改之前)非常简单:

require 'test_helper'

class TransactionsControllerTest < ActionController::TestCase
  test "should get show" do
    get :show   
    assert_response :success 
  end

end

我将它修改为上面的当前版本,因为(我相信)测试应该首先创建一个事务,然后以某种方式引用 id。但我不确定我这样做是否正确。

我在 Stackoverflow 上看到过类似的问题。例如,这个问题很有帮助,但并没有让我明白 Count; find User with id= Minitest

注意:最初,我错误地设置了控制器。我将其设置为单数“TransactionController”并将其更改为复数“TransactionsController”。所以我也不得不在单元测试中更改名称。也许这对应用产生了影响。

所以...问题:

  1. 为什么实际显示操作时单元测试失败
    在浏览器中工作?
  2. 如何更改单元测试中的代码,使其能够识别 我正在使用 transaction_params?
  3. 当我对设备进行更改时,我是否必须修改固定装置? unit_test 还是控制器?

【问题讨论】:

  • 你能试试Transaction.create!吗?也许你有一个验证错误,事务没有保存在数据库中
  • 有趣。现在导致以下错误:“ActiveRecord::RecordInvalid: Validation failed: Month can't be blank, Account code can't be blank”。我将在上面发布模型。
  • 现在看起来很清楚了,对吧? :)
  • 我会说这绝对不清楚。 :) 然而,经过一些研究和反复试验,我设法让它通过了。我会发布我自己的答案,但我可能需要 2 天才能弄清楚我做了什么!
  • 您正在创建一个没有属性的交易,因此验证未通过,因为需要月份和帐户代码。您必须调用 Transaction.create(attributes) 其中属性是一个哈希

标签: ruby-on-rails ruby unit-testing controller fixtures


【解决方案1】:

好的,所以 coorasse 建议使用 create!强制应用程序发现验证错误。最初的错误(Couldn't find Transaction with 'id'= )被替换为新错误:

ActiveRecord::RecordInvalid: 验证失败:月份不能为空, 帐号代码不能为空

这令人困惑,因为它让我想到了模型验证错误。为什么我在 ControllerTest 中收到模型验证错误?此外,transaction.rb 模型清楚地表明我已经添加了验证来满足 Month 和 AccountCode 的存在。

所以,我花了一些时间阅读 RailsGuides 上的“测试 Rails 应用程序指南” http://guides.rubyonrails.org/testing.html 一直到第 8 节,它展示了如何在每次测试之前包含一个代码块。这是新的 transaction_controller_test

transaction_controller_test.rb(修订版)

require 'test_helper'

class TransactionsControllerTest < ActionController::TestCase

    # called before every single test
  def setup
    @transaction = transactions(:one)
  end

  test "should get show" do
    get :show, id: @transaction.id
    assert_response :success 
  end

end

在此之后测试通过了!不幸的是,RailsGuides 没有告诉我为什么我想在控制器测试中使用 setup。如果任何聪明的 Rails 大师对此有一些指导,您的 cmets 将不胜感激。

【讨论】:

  • 使用无效属性创建模型时可能会引发错误 - 模型创建的原因或位置无关紧要
猜你喜欢
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多