【问题标题】:How to stub/mock multiple options depending on user input with Rspec 3.4如何根据用户输入使用 Rspec 3.4 存根/模拟多个选项
【发布时间】:2016-06-10 17:18:26
【问题描述】:

我对 Rspec 完全陌生,这是我第一次尝试在 Rails 框架之外进行测试。我只是想了解当实现非常复杂时如何模拟我的应用程序的行为。

我希望能够模仿调用customize_gender 输入选项并检查输入 1 时结果为“男性”、输入 2 时结果为“女性”等的行为。

我还希望能够检查@gender 的实例变量是否设置正确,这就是我首先添加attr_reader :gender 的原因。我一直在尝试一些事情,但我想我不明白模拟一般如何工作才能找到解决方案。我看过类似的问题,但它们似乎不适用于我的场景。非常感谢任何见解!

主文件(person.rb)

 class Person
  attr_reader :gender

  GENDER = { male: 'Male', female: 'Female', other: 'Other'}

  def initialize
    puts customize_gender
  end

  def customize_gender
    display_hash_option GENDER, 'What is your gender? '
    choice = gets.chomp.to_i
    @gender =
      case choice
      when 1
        GENDER[:male]
      when 2
        GENDER[:female]
      when 3
        print 'Enter your preferred gender: '
        gets.chomp.downcase
      else
        puts 'Error: Person -> customize_gender()'
      end
  end

  private

  def display_hash_option(hash, saying = '')
    print saying
    hash.each_with_index { |(key, _value), index| print "#{index.next}) #{key} " }
  end

end

Rspec 文件 (spec/person_spec.rb)

require_relative "../person"
describe Person do
    let(:person) { Person.new }
    allow(Person).to receive(:gets).and_return(1,2,3)
    person.customize_gender
    expect(person.gender).to eq 'Male'
    # allow(person).to receive(:customize_gender).and_return('Male')
    # expect(Person).to receive(:puts).with('What is your gender?')
    # allow(Person).to receive(:gets) { 1 }
    # expect(person.gender).to eq 'Male'
end

【问题讨论】:

    标签: ruby unit-testing rspec mocking rspec3


    【解决方案1】:

    你可以这样做,这里唯一嘲笑的是gets被设置为'1'(记住在这种情况下它是一个字符串,因为gets输入总是一个字符串)

    RSpec.describe Person do
      subject { Person.new }
    
      it 'returns male as gender when male is chosen' do
        allow(subject).to receive(:gets).and_return('1')
        subject.customize_gender
    
        expect(subject.gender).to eq('Male')
      end
    end
    

    对于when 3,您可以使用以下内容。

    RSpec.describe Person do
      subject { Person.new }
    
      it 'returns other as gender when other has been entered' do
        allow(subject).to receive(:gets).and_return('3', 'other')
        subject.customize_gender
    
        expect(subject.gender).to eq('other')
      end
    end
    

    【讨论】:

    • 这适用于简单的情况,但是when 3 子句中的嵌套获取呢?有没有办法模拟呢?我只是想找出一种优雅地适应所有边缘情况的方法。
    • 我的意思是,当用户输入3 时,它应该适用于第一种情况。但是如果用户输入 3,那么他会立即被要求输入他选择的另一个性别。例如,流程如下:enter 3 -> enter 'other' -> result should be 'other'
    • 完美!这正是我一直在寻找的。我会将其标记为已解决,但问题很快。那和allow(subject).to receive(:gets).exactly(2).times.and_return('3', 'Other')有什么区别吗?
    • 您可以将.exactly(2).times.and_returnexpect 一起使用(例如,确保它不会被调用更多)。尝试改用expect(subject).to receive(:gets).exactly(3).times.and_return('3', 'Other') 并观察结果。
    • 是的,我是从这个名字中得到的,哈哈。我只是想确定一下。感谢所有的帮助! :D
    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 2012-07-27
    • 2014-03-13
    • 2022-01-04
    相关资源
    最近更新 更多