在 Rspec 中测试随机天气方法的功能,具体取决于生成的随机数

Testing in Rspec a random weather methods functionality depending on the random number generated

我正在尝试进行 2 次测试来检查 Weather class 中方法的功能。 random_weather 方法应根据 random_number 的结果更改 @status。但是我找不到强制 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:

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)>'

您有 3 个选项:

  • 在一个方法中包装随机性并存根这个方法
  • 包装或注入一个生成器class,并在规范
  • 中注入一个非随机生成器
  • 存根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