【问题标题】:How can i test this method RSpec我如何测试这种方法 RSpec
【发布时间】:2022-07-06 03:00:38
【问题描述】:

我有这个方法 - choose_option enter image description here

还有这个帮助方法 enter image description here

问题,我如何测试并获得绿灯simpelcov。

allow(adapter).to receive(:gets).and_return('my_guess')
except(adapter).to receive(:adapter_my_guess)

但这不起作用 错误:

expected: 1 time with any arguments
received: 2 times

因为我的包装器一直调用 choose_option 看起来像递归

def adapter_my_guess(guess)
  @game.instance_variable_set(:@secret_code, %w[1 2 3 4])
  if @game.attempts.positive?
     puts show_guess_result(@game.my_guess(guess))
  else
     puts I18n.t(:lose_game, secret_code: @game.instance_variable_get(:@secret_code))
  end
end

def wrapper(method_for_wrap)
  puts method_for_wrap
  @game.win == false ? choose_option : Finishe.new(@game, @statistics).finishe
end

def choose_option
  option = input(I18n.t(:start_game_options, option1: OPTION_1, option2: OPTION_2, exit: EXIT))
  case option
  when OPTION_1 then wrapper(adapter_my_guess(input(I18n.t(:puts_guess, exit: OR_EXIT))))
  when OPTION_2 then wrapper(adapter_give_hints)
  else
    raise(StandardError, WRONG_OPTION)
  end
rescue StandardError => e
  puts e
  choose_option

结束

【问题讨论】:

  • 图像中的代码很难处理。请将您的代码粘贴到问题中好吗?
  • 你好,我会试试的!
  • 我只需要在 adapter_my_guess 中测试所有案例
  • 您没有测试adapter_my_guess 中的代码,因为except(adapter).to receive(:adapter_my_guess) 正在模拟它。我们可以看看你的测试吗?
  • 抱歉,我需要在 choose_option 中测试所有情况,for_adapter 游戏我已经测试过了,抱歉。

标签: ruby recursion rspec


【解决方案1】:

except(adapter).to receive(:adapter_my_guess) 表示adapter 将收到一个且只有一个呼叫adapter_my_guess。收到了两个。

如果正确,请添加change your expectation to expect more calls at_least(1).time

如果这不正确,我们需要更多地了解您的代码和测试。


一些笔记...

不要在生产代码中使用instance_variable_getinstance_variable_set。获取其他对象的内部变量会使代码纠缠不清,并且很难在没有不可预见的后果的情况下更改对象。将secret_code 设为正确的accessor method

choose_option 做了三件事。它获取选项,解释选项,并决定是否需要再次获取选项。将其拆分为三种方法,一种获取选项,一种解释选项,一种将它们放在一起。这样会更灵活,更容易测试。

捕获每个 StandardError 的范围太广了。随着方法的拆分,选项是方法的参数。您可以将异常更改为更具体的ArgumentError

def get_option
  input(I18n.t(:start_game_options, option1: OPTION_1, option2: OPTION_2, exit: EXIT))
end

def do_option(option)
  case option
  when OPTION_1 then wrapper(adapter_my_guess(input(I18n.t(:puts_guess, exit: OR_EXIT))))
  when OPTION_2 then wrapper(adapter_give_hints)
  else
    raise(ArgumentError, WRONG_OPTION)
  end
end

def choose_option
  do_option(get_option)
rescue ArgumentError
  choose_option
end

现在每个都可以进行单元测试,而无需模拟整个过程。例如,我们在choose_option 中需要测试的只是它是否获得了一个选项,尝试用它做某事,然后重试。

describe '#choose_option' do
  context 'with a good option' do
    it 'gets and does the option once' do
      option = double

      expect(adapter).to receive(:get_option)
        .and_return(option)
      expect(adapter).to receive(:do_option)
        .with(double)

      adapter.choose_option
    end
  end

  context 'with a bad option' do
    it 'gets and does the option again' do
      good_option = double
      bad_option = double

      # This will raise an ArgumentError.
      expect(adapter).to receive(:do_option)
        .with(bad_option)
        .and_call_original

      # This will not.
      expect(adapter).to receive(:do_option)
        .with(good_option)

      # First use the bad option, then the good one.
      expect(adapter).to receive(:get_option)
        .and_return(bad_option, good_option)

      adapter.choose_option
    end
  end    
end

我们不需要知道do_optionget_option 做了什么来测试choose_option,它们完全可以被嘲笑。 do_optionget_option 可以单独进行单元测试。

【讨论】:

  • 是的,但是当我更改一次或两次或至少等时。我收到最多,因为:当choose_option得到-> def wraper puts(method wich user input) -> 并重新调用choose_option
  • 当用户输入退出或用户赢得游戏 => 选择选项关闭
  • choose_option 做的太多了。查看我对如何分解它的修改。
猜你喜欢
  • 1970-01-01
  • 2017-12-19
  • 2013-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
  • 2019-10-03
相关资源
最近更新 更多