0

我有一个使用 Ruby 测试的 API 端点。我有 8 个测试,如下所示:

it "must rate limit on this api" do

  body = {
    ..
  }

  # Current limits assigned to this api endpoint are 5 requests every 5 minutes.
  # So this test will make 5 calls in short succession to trigger the rate limiter
  with_logging_suppressed do
    5.times do
      post '/api/endpoint/', body.to_json
      last_response.status.must_equal 200
    end

    post '/api/endpoint/', body.to_json
    last_response.status.must_equal 429
    last_response.body.include? "You are doing this too often"
  end
end

当您 POST 到 时/api/endpoint/,它会生成一个RateLimit包含validate_rate?方法的类,并使用一个实例变量,@timestamp该实例变量是调用 API 时的时间戳数组。

RATE_LIMIT = RateLimit.new(5, 5.minutes)
post '/api/endpoint/' do
  if RATE_LIMIT.validate_rate?
    ...
  else
    throw Error
  end
end

RateLimit将包含以下@timestamp实例变量以及以下validate_rate?将与之进行比较的时间戳示例。

@timestamp = [2018-04-16 19:17:48 -0400, 2018-04-16 19:17:49: -0400, 2018-04-16 19:17:58 -0400]

但是,在每次测试运行之前,我必须清除@timestamp数组,否则数组将包含以前测试的时间戳,这当然会破坏测试结果

因此,我尝试@timestamp在每次测试运行之前以before块的形式将数组设置为新数组。

before do
  RateLimit.instance_variable_set(:@timestamp, [])
end

我目前遇到的问题是,由于该RateLimit实例不是在此测试中专门创建的,所以当我调用 时,如果这有意义post /api/endpoint/,我似乎无法设置变量。@timestamp它确实将 a 设置@timestamp[],但它没有设置在我运行实际测试时创建的特定实例

我想保持@timestamp私有,所以我不想创建一个让我获取或设置这个私有变量的方法,所以我唯一的选择似乎是instance_variable_set.

4

1 回答 1

-1

您应该存根另一种方法:

before do
  allow_any_instance_of(RateLimit).to receive(validate_rate?).and_return(true)
end

然后RateLimit.new在单独的测试示例中进行测试

于 2018-04-17T08:05:02.587 回答