Open aisrael opened 6 years ago
I'd really like to have this resolved, so I can perform proper hi8
testing of my code that does repeated API calls (with the same "signature") to an external Web service.
To wit: all the interactions are being recorded properly. It's just that the way hi8
sets up the mocks for testing, it does it all at once before the test. Hence, subsequent calls to the same URL with the same headers get matched/mocked to the first call.
I'd be more than willing to dive into this and submit a pull request if there are no objections?
Hi @aisrael, I think that the sequencing you are trying to achieve can be done with a single stub using a block and letting the logic of which is the expected response to the block.
Isn't that enough to support your use case without changing this shard?
I think it could, if I wasn't using Hi8. My issue is that stubbing requires you to know all the calls (and their exact signatures) beforehand, then you have to setup the stubs beforehand, and all that. What Hi8 (VCR) does is simply record all HTTP interactions once on first run, then play them back on subsequent runs.
Also, I've checked with Ruby's own webmock
gem and webmock
does "consume" requests after they're matched.
I realize I can probably get by with simply "monkey-patching" your shard in every project we have that uses it... but that's not ideal either as the number of projects grows.
Ok, I see. I am not familiar with vcr semantics, but if the stubs are removed after match I guess that it does not enforce the order in the trace, right? If it should then the consume_after_match is not enough.
That's true, and the thought did occur to me earlier as I was thinking of other ways to accomplish this (one way is to require Hi8 itself to keep track of all calls matching the same signature, then manage its own queue, removing stubs/responses as they're matched).
At least, for my current use cases it does work: Hi8 records the calls as they occur. Then, during mocking, it calls Webmock.stub
for each interaction. That in turn appends each stub (regardless of signature) to StubRegistry
into the ivar @stubs
(which is an Array(Stub)
).
Then, Hi8/Webmock attempts to match each call to a with StubRegistry#find_stub
(which uses Array#find
) which does perform a linear search. On a match, with consume_after_match
we just Array#delete
the found Stub
. Thus, the order of the calls are preserved.
This is related to issue https://github.com/vonKingsley/hi8.cr/issues/9
Background
HI8 will create two stubs for two consecutive HTTP interactions ("episodes") with identical request signatures.
However, when HI8 starts playing back requests, Webmock will match the second request with the first stub.
Expected Behaviour
response.body == "1"
response.body == "2"
Actual Behaviour
Possible Solutions
after_request
callbackIf WebMock.cr had an
after_request
callback, it might be possible to tell WebMock to remove the first stub after the first request. For that to happen, we could eitheryield
theStubRegistry
to the callback, or provide a class getterWebMock.registry
for@@registry
.Provide option
WebMock.consume_stub(request)
andWebMock.consume_after_match?
optionWe could set a boolean option e.g.
WebMock.consume_after_match = true
, and in core_ext.cr#L11 add e.g.Other options might be specifying a numeric TTL per stub indicating how many times it should be used to match a request before it's discarded/consumed.