I have an API endpoint I'm testing using Ruby. I have 8 tests that look like the following:
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
When you POST to /api/endpoint/
, it spawns a RateLimit
class which contains a validate_rate?
method and it uses an instance variable of @timestamp
which is an array of timestamps of when the API has been called.
RATE_LIMIT = RateLimit.new(5, 5.minutes)
post '/api/endpoint/' do
if RATE_LIMIT.validate_rate?
...
else
throw Error
end
end
RateLimit
would contain the following @timestamp
instance variable with the following sample of timestamps which validate_rate?
would compare against.
@timestamp = [2018-04-16 19:17:48 -0400, 2018-04-16 19:17:49: -0400, 2018-04-16 19:17:58 -0400]
However, prior to each test run, I MUST clear out the @timestamp
array or the array will contain timestamps from previous tests, which of course ruins the test results
So I attempted to try to set the @timestamp
array to a new array prior to each test run in the form of a before
block.
before do
RateLimit.instance_variable_set(:@timestamp, [])
end
The issue I am currently running into right now is that because the RateLimit
instance isn't specifically created in this test, when I call post /api/endpoint/
, I cannot seem to set the @timestamp
variable if this makes sense. It does set a @timestamp
to []
, but it's not setting the specific instance that was created when I am running the actual test
I want to keep @timestamp
private, so I do not want to create a method that lets me get or set this private variable, so my only choice seems to be instance_variable_set
.