【问题标题】:How to test class method using rspec如何使用 rspec 测试类方法
【发布时间】:2018-03-28 15:50:00
【问题描述】:

您好,我正在使用 ruby​​-2.5.0 和 rails 5.0 开发 RoR 项目。我有一个模型 forgot_password ,其中定义了一个类方法来创建记录,如下所示:-

forgot_password.rb
# frozen_string_literal: true

class ForgotPassword < ApplicationRecord
  before_create :create_token

  def self.create_record
    self.create!(expiry: Time.zone.now +
                 ENV['VALIDITY_PERIOD'].to_i.hours)
  end

  private

  def create_token
    self.token = SecureRandom.urlsafe_base64(nil, false)
  end
end

我想使用 stub 或 factory_girl gem 为其编写单元测试。

spec/models/forgot_password_spec.rb
# frozen_string_literal: true

require 'rails_helper'

describe ForgotPassword do
  let(:forgot_password) do
    described_class.new()
  end

  describe 'create_record' do
    context 'with forgot_password class' do
      subject { forgot_password.create_record.class }

      it { is_expected.to eq ForgotPassword }
    end
  end
end

但它的抛出错误undefined method create_record for #&lt;ForgotPassword:0x000000000622bc98&gt; 请帮助我如何测试我的模型。提前致谢。

【问题讨论】:

  • 停止实例化所描述类的实例?
  • 对不起,我没有明白你的意思
  • 如何在有类方法和 before_create 回调的地方测试我的模型?

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


【解决方案1】:

你写的是一个工厂方法(一个返回实例的类方法)你应该调用它并写下关于返回实例的期望:

describe ForgotPassword do
  describe ".create_record" do
    subject { described_class.create_record! }
    it { is_expected.to be_an_instance_of(described_class) }
    it "sets the expiry time to a time in the future" do
      expect(subject.expiry > Time.now).to be_truthy
    end
  end
end

但是,如果您真正想做的是设置一个计算出的默认值,那么还有一种不那么笨拙的方法:

class ForgotPassword < ApplicationRecord
  after_initialize :set_expiry!

  private

  def set_expiry!
    self.expiry(expiry: Time.zone.now).advance(hours: ENV['VALIDITY_PERIOD'].to_i)
  end
end

或者使用 Rails 5:

class ForgotPassword < ApplicationRecord
  attribute :expiry, :datetime, 
    ->{ Time.zone.now.advance(hours: ENV['VALIDITY_PERIOD'].to_i) }
end

您可以通过以下方式对其进行测试:

describe ForgotPassword do
  let(:forgot_password){ described_class.new }
  it "has a default expiry" do
    expect(forgot_password.expiry > Time.now).to be_truthy
  end
end

【讨论】:

    【解决方案2】:

    您可以直接针对described_class 进行测试: 需要'rails_helper'

    describe ForgotPassword do
      context 'with forgot_password class' do
        subject { described_class }
    
        it { is_expected.to eq ForgotPassword }
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-20
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多