【问题标题】:Testing custom validators with Minitest使用 Minitest 测试自定义验证器
【发布时间】:2015-11-28 21:13:53
【问题描述】:

我有多个带有电子邮件验证的模型。因此,我已将验证提取到自定义验证器中。我是按照Rails Guides 的教程做的。

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
      record.errors[attribute] << (options[:message] || "is not an email")
    end
  end
end

到目前为止,一切都很好。但是由于我已经将电子邮件验证的功能提取到它自己的范围内,所以我也想单独测试它。我不想为每个模型添加相同的电子邮件格式测试。

我找到了另一个question,它也问了同样的问题,但对于 RSpec。但由于我还没有使用存根和模拟,我不知道如何将测试移植到 Minitest 测试。我没有找到任何使用 Minitest 测试自定义验证器的资源。

有人知道如何在 Minitest 中为自定义验证器编写此类测试(不使用规范!)?

【问题讨论】:

    标签: ruby-on-rails validation unit-testing minitest custom-validators


    【解决方案1】:

    您在这里要求的(我认为)是在隔离中测试此验证器。这意味着它将在一个独立的测试中测试一次,这将完全按照您所说的进行:

    我不想为每个模型添加相同的电子邮件格式测试。

    我在这里采用的方法是在测试文件中创建一个测试类,混合ActiveRecord::Validations 模块并测试该类本身。

    # test_file.rb
    require 'test_helper'
    
    class EmailValidatable
      include ActiveModel::Validations
      validates_with EmailValidator
      attr_accessor  :email
    end
    
    class EmailValidatorTest < Minitest::Test
      def test_invalidates_object_for_invalid_email
        obj = EmailValidatable.new
        obj.email = "invalidemail"
        refute obj.valid?
      end
    
      def test_adds_error_for_invalid_email
        obj = EmailValidatable.new
        obj.email = "invalidemail"
        refute_nil obj.errors[:email]
      end
    
      def test_adds_no_errors_for_valid_email
        obj = EmailValidatable.new
        obj.email = "valid@email.com"
        assert_nil obj.errors[:email]
        assert obj.valid?
      end
    end
    

    我没有测试过上面的代码,但我认为它应该给你一个想法/方向。

    HTH

    【讨论】:

    • 这正是我要寻找的。我从没想过创建一个新类并从那里测试它。我一直在寻找一种直接测试它的方法。但这看起来更好!谢谢!
    • 太好了,我很高兴能帮上忙。你能对你的完整测试进行检查吗?谢谢:)
    • 嗨@Ile!我已经添加了我实施的解决方案作为答案。再次感谢您!
    【解决方案2】:

    这是我根据 Ile Eftimov 的回答实施的解决方案:

    require 'test_helper'
    
    class EmailValidatable
        include ActiveModel::Validations
        attr_accessor :email
    
        validates :email, email: true
    end
    
    class EmailValidatorTest < ActiveSupport::TestCase
        invalid_email_addresses = ['invalid email@example.com', 'invalid@ example.com', 'invalid@@example.com', 'invalid', 'invalid@example']
    
        def obj; @obj ||= EmailValidatable.new; end
    
        test 'should invalidate email address' do
            invalid_email_addresses.each do |email|
                obj.email = email
                assert_not obj.valid?
            end
        end
    
        test 'should add error for invalid email' do
            invalid_email_addresses.each do |email|
                obj.email = email
                obj.valid?
                assert_equal I18n.t('errors.messages.not_an_email_address'), obj.errors[:email][0], "no error message for invalid email address \"#{email}\""
            end
        end
    
        test 'should validate email address' do
            obj.email = FFaker::Internet.email
            assert obj.valid?
        end
    
        test 'should add no error for valid email' do
            obj.email = FFaker::Internet.email
            assert obj.errors[:email].blank?
        end
    end
    

    非常酷的解决方案,也可用于其他测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多