【问题标题】:Rspec2 testing a before_validation methodRspec2 测试 before_validation 方法
【发布时间】:2011-09-09 11:35:04
【问题描述】:

我有以下内容可以删除特定属性上的空格。

#before_validation :strip_whitespace

protected
  def strip_whitespace
    self.title = self.title.strip
  end

我想测试一下。目前,我已经尝试过:

it "shouldn't create a new part with title beggining with space" do
   @part = Part.new(@attr.merge(:title => " Test"))
   @part.title.should.eql?("Test")
end

我错过了什么?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 unit-testing rspec rspec2


    【解决方案1】:

    在保存对象或手动调用 valid? 之前,验证不会运行。您的 before_validation 回调未在您当前的示例中运行,因为您的验证从未被检查过。在您的测试中,我建议您先运行@part.valid?,然后再检查标题是否已更改为您所期望的。

    app/models/part.rb

    class Part < ActiveRecord::Base
      before_validation :strip_whitespace
    
    protected
      def strip_whitespace
        self.title = self.title.strip
      end
    end
    

    spec/models/part_spec.rb

    require 'spec_helper'
    
    describe Part do
      it "should remove extra space when validated" do
        part = Part.new(:title => " Test")
        part.valid?
        part.title.should == "Test"
      end
    end
    

    包含验证时会通过,注释掉验证时会失败。

    【讨论】:

    • 即使我评论了before_validation 行,测试也通过了。
    • 我添加了一个快速测试中的代码,我把它放在一起按预期工作。如果您仍然遇到问题,那么您的应用中肯定有一些不同之处,因此我们可能需要查看更多代码以提供进一步帮助
    • 看来.eql?("Test") 的行为与== "Test" 不同。改变这一点,测试按预期工作。谢谢@danivovich!
    • 非常有趣。仔细查看 rspec 文档表明 should.eql?不是检查相等性的预期用途,请使用==eq(..)。我认为您的行只是评估“测试”与匹配器不同,但没有断言任何内容。 relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/…
    【解决方案2】:

    参考@danivovich的例子

    class Part < ActiveRecord::Base
      before_validation :strip_whitespace
    
    protected
      def strip_whitespace
        self.title = self.title.strip
      end
    end
    

    编写规范的正确方法是在 strip_whitespace 方法上单独编写规范,然后检查模型类是否设置了回调,如下所示:。

    describe Part do
      let(:record){ described_class.new }
    
      it{ described_class._validation_callbacks.select{|cb| cb.kind.eql?(:before)}.collect(&:filter).should include(:strip_whitespace) }
    
      #private methods
      describe :strip_whitespace do
        subject{ record.send(:strip_whitespace)} # I'm using send() because calling private method
        before{  record.stub(:title).and_return('    foo    ')
        it "should strip white spaces" do
          subject.should eq 'foo'
          # or even shorter
          should eq 'foo'
        end
      end
    end
    

    如果您需要在某些情况下跳过回调行为,请使用

    before{ Part.skip_callback(:validation, :before, :strip_whitespace)}
    before{ Part.set_callback( :validation, :before, :strip_whitespace)}
    

    2013 年 1 月 20 日更新

    顺便说一句,我用 RSpec 匹配器写了一个 gem 来测试这个 https://github.com/equivalent/shoulda-matchers-callbacks

    一般来说,我完全不推荐回调。例如在这个问题中它们很好,但是一旦你做了更复杂的事情,比如:

    创建后->

    • 将帐户链接到用户
    • 创建通知
    • 向管理员发送电子邮件

    ...那么您应该创建自定义服务对象来处理这个问题并单独测试它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2023-03-16
      相关资源
      最近更新 更多