【问题标题】:Simple syntax for testing Validation errors用于测试验证错误的简单语法
【发布时间】:2009-09-26 15:53:45
【问题描述】:

我正在寻找干净和简短的代码来测试 Rails 单元测试中的验证。

目前我正在做这样的事情

test "create thing without name" do
    assert_raise ActiveRecord::RecordInvalid do
        Thing.create! :param1 => "Something", :param2 => 123
    end
end

我想还有更好的方法来显示验证消息吗?

解决方案:

我目前没有额外框架的解决方案是:

test "create thing without name" do
    thing = Thing.new :param1 => "Something", :param2 => 123
    assert thing.invalid?
    assert thing.errors.on(:name).any?
end

【问题讨论】:

  • 感谢您的回复。我会尝试 rspec 和其他一些时间。现在我用 assert(record.invalid?) 和 assert_equal([], record.errors.full_messages) 来帮助自己

标签: ruby-on-rails unit-testing validation


【解决方案1】:

您没有提及您正在使用什么测试框架。许多都有宏,可以让测试 activerecord 变得轻而易举。

这是在不使用任何测试助手的情况下完成此任务的“漫长道路”:

thing = Thing.new :param1 => "Something", :param2 => 123
assert !thing.valid?
assert_match /blank/, thing.errors.on(:name)

【讨论】:

  • 我目前只使用普通的 Rails。
  • 从 Rails 3 开始,ActiveModel::Errors 没有“on”方法。 stackoverflow.com/questions/7526499/…
  • 这个答案可能已经过时了,但assert_match 不适用于数组。
【解决方案2】:

我使用的是 Rails 2.0.5,当我想断言模型将无法通过验证时,我会检查 errors.full_messages method,并将其与一系列预期消息进行比较。

created = MyModel.new
created.field1 = "Some value"
created.field2 = 123.45
created.save

assert_equal(["Name can't be blank"], created.errors.full_messages)

为了断言验证成功,我只是比较一个空数组。您可以执行非常类似的操作来检查 Rails 控制器在创建或更新请求后是否没有错误消息。

assert_difference('MyModel.count') do
  post :create, :my_model => {
    :name => 'Some name'
  }
end

assert_equal([], assigns(:my_model).errors.full_messages)
assert_redirected_to my_model_path(assigns(:my_model))

【讨论】:

    【解决方案3】:

    对于那些使用 Rails 3.2.1 及更高版本的用户,我更喜欢使用added? 方法:

    assert record.errors.added? :name, :blank
    

    我使用如下所示的测试助手:

    def assert_invalid(record, options)
      assert_predicate record, :invalid?
    
      options.each do |attribute, message|
        assert record.errors.added?(attribute, message), "Expected #{attribute} to have the following error: #{message}"
      end
    end
    

    这让我可以编写这样的测试:

    test "should be invalid without a name" do
      user = User.new(name: '')
    
      assert_invalid user, name: :blank
    end
    

    【讨论】:

      【解决方案4】:

      也试试accept_values_for gem。 它允许做这样的事情:

      describe User do
      
        subject { User.new(@valid_attributes)}
      
        it { should accept_values_for(:email, "john@example.com", "lambda@gusiev.com") }
        it { should_not accept_values_for(:email, "invalid", nil, "a@b", "john@.com") }
      end
      

      通过这种方式,您可以轻松测试非常复杂的验证

      【讨论】:

        【解决方案5】:

        在带有 MiniTest 的新版 Rails (v5) 中

        test "create thing without name" do
            thing = Thing.new :param1 => "Something", :param2 => 123
            assert thing.invalid?
            assert thing.errors.added? :name, :blank
        end
        

        https://devdocs.io/rails~5.2/activemodel/errors

        【讨论】:

          【解决方案6】:

          你可以试试rspec-on-rails-matchers。为您提供如下语法:

          @thing.should validates_presence_of(:name)
          

          【讨论】:

          • 页面上写着:不要使用我。我已经过时了,我打破了应该。应该现在与 rspec 一起工作。使用它。
          猜你喜欢
          • 2015-12-28
          • 1970-01-01
          • 2020-10-23
          • 1970-01-01
          • 2016-04-18
          • 1970-01-01
          • 1970-01-01
          • 2017-12-11
          • 2013-03-18
          相关资源
          最近更新 更多