我需要在这个方法中存根一切才能通过吗?

时间:2016-03-17 18:40:06

标签: ruby-on-rails mocha minitest

我通常是摩卡新手,我讨厌使用这个宝石,但我需要使用它来传递我正在构建的测试。给我带来问题的是我应该嘲笑的东西以及我应该如何嘲笑它。为了说明我的观点,以下是我正在测试的方法示例:

 def statistics_of_last_24_hrs
    stats = ses.statistics.find_all { |s| s[:sent].between?(Time.now.utc - 24.hours, Time.now.utc) }
    sent_last_24_hrs = ses.quotas[:sent_last_24_hours].to_f
    no_of_bounces = stats.inject(0.0) { |a, e| a + e[:bounces] }
    no_of_complaints = stats.inject(0.0) { |a, e| a + e[:complaints] }
    bounce_rate = sent_last_24_hrs.zero? ? 0.0 : (no_of_bounces / sent_last_24_hrs) * 100
    complaint_rate = sent_last_24_hrs.zero? ? 0.0 : (no_of_complaints / sent_last_24_hrs) * 100
    fail(Reverification::SimpleEmailServiceLimitError, 'Bounce Rate exceeded 5%') if bounce_rate >= 5.0 
    fail(Reverification::SimpleEmailServiceLimitError, 'Complant Rate exceeded .1%')if complaint_rate >= 0.1 
  end

基本上,此代码正在执行的操作是从Amazon api调用获取一些统计信息,然后计算它们以确定我的跳出/投诉率是否超出限制。限额分别为5%和0.1%。

基本上,对于我的测试,我真正需要做的是将变量bounce_ratecomplaint_rate存根,以便测试是否抛出了正确的异常。

这是我陷入困境的地方。这是一个我最好写的准系统测试:

it 'should raise SimpleEmailServieLimitError if bounce rate is above 5%' do
  assert_raise Reverification::SimpleEmailServiceLimitError do
     Reverification::Process.statistics_of_last_24_hrs
  end
end

如何将bounce_ratecomplaint_rate存根。我已经做了一些搜索并得出结论,没有办法存根变量。我也查看了这个链接List of Mocha Methods这证实了我的发现。

有没有办法可以像这样写一个测试:

 it 'should raise SimpleEmailServieLimitError if bounce rate is above 5%' do
  stubs(:bounce_rate).returns(true)
  assert_raise Reverification::SimpleEmailServiceLimitError do
     Reverification::Process.statistics_of_last_24_hrs
  end
end

或者我必须在此方法中存根每个方法调用,以便测试看起来像这样:

it 'should raise SimpleEmailServieLimitError if bounce rate is above 5%' do
  sent_last_24_hrs = 20
  over_bounce_limit = MOCK::AWS::SimpleEmailService.over_bounce_limit
  AWS::SimpleEmailService.any_instance.stubs(:statistics).returns(stub(find_all: over_bounce_limit))
  AWS::SimpleEmailService.any_instance.stubs(:quotas).returns(stub(sent_last_24_hours: sent_last_24_hrs))
  etc. etc. etc...........
  assert_raise Reverification::SimpleEmailServiceLimitError do
     Reverification::Process.statistics_of_last_24_hrs
  end
end

有更简单的方法吗?

1 个答案:

答案 0 :(得分:0)

即使存在存根局部变量的方法,该功能也会产生很难维护的测试,因为您无法在不更改测试的情况下重构代码。

嵌套存根也有设计气味 - 你的测试会知道太多的实现细节,并且会变得无法维护。

对于存根第三方代码也是如此,因为对第三方库的任何更改都将允许您的测试在代码不起作用时通过。

围绕AWS SimpleEmailService - gateway创建自己的包装器要好得多。你实现它有一个非常狭窄的稳定界面,如

class BounceStatistics
  def no_of_bounces
  def no_of_complaints
  def sent_last_24_hrs
end

由于此接口是您自己的并且它是稳定的,因此您可以安全地存根并为测试提供替代实现:

assert_raise Reverification::SimpleEmailServiceLimitError do
  Reverification::Process.statistics_of_last_24_hrs(
    stub(no_of_bounces: 2, no_of_complaints: 3, sent_last_24_hrs: 5))
end

或者您可以将其实现为

BounceStatistics.any_instance.stubs(:no_of_bounces).returns(2)
BounceStatistics.any_instance.stubs(:no_of_complaints).returns(3)
BounceStatistics.any_instance.stubs(:sent_last_24_hrs).returns(5)

assert_raise Reverification::SimpleEmailServiceLimitError do
  Reverification::Process.statistics_of_last_24_hrs
end

但是,明确地传递依赖项可以让您拥有更多可维护的代码和更简单的测试。