首页 > 解决方案 > 根据生成的随机数在 Rspec 中测试随机天气方法功能

问题描述

我正在尝试进行 2 次测试来检查Weather类中方法的功能。该random_weather方法应@status根据random_number. 但是我找不到强制random_number成为某个数字的方法。

RSpec 测试:

require 'weather'

describe Weather do
  subject { Weather.new }

  it 'Can create an instance of Weather' do
    expect(subject).to be_instance_of Weather
  end

  it 'Can return sunny when randomly choosing weather' do
    subject.stub(:generate_random_number) {5}
    expect(subject.status).to eq "Sunny"
  end

  it 'Can return stormy when randomly choosing weather' do
    subject.stub(:generate_random_number) {9}
    expect(subject.status).to eq "Stormy"
  end
end

天气等级:

class Weather
  attr_reader :status, :random_number

  def initialize
    @random_number = generate_random_number
    puts @random_number
    if (1..8).include?(@random_number)
      @status = "Sunny"
    else
      @status = "Stormy"
    end
  end

  def generate_random_number
    rand(1..10)
  end
end

失败示例:

  1) Weather Can return stormy when randomly choosing weather
     Failure/Error: expect(subject.status).to eq "Stormy"

       expected: "Stormy"
            got: "Sunny"

       (compared using ==)
     # ./spec/weather_spec.rb:17:in `block (2 levels) in <top (required)>'

标签: rubyclassrspec

解决方案


您有 3 个选项:

  • 在方法中包装随机性并存根此方法
  • 包装或注入的生成器类,并在规范中注入非随机生成器
  • 存根rand

我更喜欢第二种选择,但第一种可能就足够了。

私有方法

class Weather
  attr_reader :status, :random_number

  def random_weather
    @random_number = generate_random_number
    # ...
  end

  def generate_random_number
    rand(1..10)
  end
end

#specs
  it 'Can return sunny when randomly choosing weather' do
    subject.stub(:generate_random_number) {5}
    expect(subject.status).to eq "Sunny"
  end

发电机注入

class Weather
  attr_reader :status, :random_number
  def initialize(random_number_generator: RandomNumberGenerator)
    @random_number_generator = random_number_generator
  end

  def random_weather
    @random_number = random_number_generator.call
    # ...
  end
end

class RandomNumberGenerator
  def self.call
    rand(1..10)
  end
end

#specs
  subject { described_class.new(generator) }
  let(:generator) { ->{ 5 } }    
  it 'Can return sunny when randomly choosing weather' do
    expect(subject.status).to eq "Sunny"
  end

rand规范中的存根

  it 'Can return sunny when randomly choosing weather' do
    stub(:rand) {5}
    expect(subject.status).to eq "Sunny"
  end

推荐阅读