如何防止Rails控制器测试在模型中出现错误?

时间:2015-10-02 03:45:42

标签: ruby-on-rails ruby ruby-on-rails-4

manager.rb(型号)

class Manager < ActiveRecord::Base
  belongs_to :player
  belongs_to :season
  belongs_to :team

  before_validation :validate_relations

  validates :player_id, presence: true
  validates :season_id, presence: true
  validates :team_id, presence: true

  private

  def validate_relations
    player = Player.find(self.player_id)
    season = Season.find(self.season_id)
    team = Team.find(self.team_id)

    manager = Manager.find_by(player: player, season: season, team: team)

    if !manager.nil? && self.id != manager.id
      errors[:manager] << 'already exists.'
      false
    end
  end
end

managers_controller.rb(controller)

class ManagersController < ApplicationController
  before_action :get_manager, only: [:destroy, :show, :update]
  rescue_from ActionController::ParameterMissing, with: :malformed_request
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  def create
    @manager = Manager.create(manager_params)
    status = @manager.valid? ? :no_content : :unprocessable_entity

    render_manager status
  end

  ...

  private

  def manager_params
    params.require(:manager).permit(:player_id, :season_id, :team_id, :league_id)
  end

  def malformed_request
    render_manager :unprocessable_entity, 'Error message'
  end

  def record_not_found
    render_manager :not_found, 'Error message'
  end

  def get_manager
    @manager = Manager.includes(:player, :season, :team).find(params[:id])
  end

  def render_manager(status, message = nil)
    ...
  end

  def render_managers(status, managers)
    ...
  end
end

如您所见,我的managers_controllerActiveRecord::RecordNotFound获救并在客户端尝试创建无效的关联ID时相应地处理相应的响应。当明确给出请求和响应时,这很有效,但是当我rake test时,使用无效的关联id(例如,当所有id都是nil时)的测试总是以3个错误结束,表明rails无法找到具有给定ID的每个Model,如下所示。

  1) Error:
ManagerTest#test_: Manager should require player_id to be set. :
ActiveRecord::RecordNotFound: Couldn't find Player with 'id'=
    app/models/manager.rb:35:in `validate_relations'


  2) Error:
ManagerTest#test_: Manager should require season_id to be set. :
ActiveRecord::RecordNotFound: Couldn't find Player with 'id'=
    app/models/manager.rb:35:in `validate_relations'


  3) Error:
ManagerTest#test_: Manager should require team_id to be set. :
ActiveRecord::RecordNotFound: Couldn't find Player with 'id'=
    app/models/manager.rb:35:in `validate_relations'

如何重新设计测试,模型验证或错误处理以避免这些错误?

3 个答案:

答案 0 :(得分:1)

您的Manager模型似乎需要验证,以根据TeamSeasonPlayer模型检查当前模型是否唯一。有一个内置的验证器,称为uniquenessdetailed docs),您只需要:

class Manager < ActiveRecord::Base
  belongs_to :player
  belongs_to :season
  belongs_to :team

  validates :player_id, uniqueness: { scope: [:team_id, :season_id] }
end

您也可以使用shoulda-matchers进行测试。

答案 1 :(得分:0)

通常,对于单元测试,您希望测试一个独立于另一个类的类,因此在您的情况下,您希望独立于模型测试控制器,因此您应该提供模型的“模拟”。

我不确定您使用的测试框架,但这里是rspec文档中的example

您使用FactoryGirl创建样本模型数据。

答案 2 :(得分:0)

除了测试方法之外,我觉得很奇怪,验证会抛出一个not_found ......为什么不在你的验证中拯救(或使用Player.find_by(:id => self.player_id),这将返回nil) ,所以你可以返回如下信息:

{
 :errors => [
   { "Player" => "not found" },
   { "Season" => "not valid" },   
   { "Team" => "not whatever" }
 ]
}