簡體   English   中英

使用Minitest測試自定義驗證器

[英]Testing custom validators with Minitest

我有多個模型與電子郵件驗證。 因此,我已將驗證提取到自定義驗證器中。 我按照Rails指南的教程來說明這一點。

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

到現在為止還挺好。 但是,由於我已經將電子郵件驗證的功能提取到了自己的范圍內,我還想單獨測試它。 我不想為每個模型添加相同的電子郵件格式測試。

我發現了另一個問題 ,但也為RSpec問了同樣的問題 但由於我還沒有使用存根和模擬,我不知道如何將測試移植到Minitest測試。 我沒有找到任何用Minitest測試自定義驗證器的資源。

有人知道如何在Minitest中為自定義驗證器編寫此類測試(不使用規范!)?

什么(我覺得)你所要求的是在這里測試該驗證程序隔離 這意味着它將在隔離測試中進行一次測試,這將完全按照您的說法進行測試:

我不想為每個模型添加相同的電子郵件格式測試。

我在這里采用的方法是在測試文件中創建一個測試類,混合使用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 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

非常酷的解決方案,也可用於其他測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM