Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added mocking forever support #72

Closed

Conversation

tasomaniac
Copy link

📌 References

Fixes #68

🎩 What is the goal?

This PR adds 2 new functions thenRespondForever and thenDispatchForever to have a behavior where the mocking mechanism is persistent until the server is shut down.

💻 How is it being implemented?

In the original code, the requests list/queue is processed when new requests are executed. And earlier mocks are removed on-the-fly when hiroaki responds. It is actually not possible to compare and remove previous matchers immediately when they're added since they don't implement equals functionality.

With this approach here is some principles I put into place:

  • Regular respond always takes priority regardless of being added before or after.
  • The most recently added respondForever takes precedence. As mentioned above, I cannot clear previous matchers immediately when a new one is added. I could potentially clear previous one when a respondForever is matched successfully. I figured that this is not a good idea since 1. it is not trivial, 2. there might be cases where previously added matcher can be useful for other requests even though it is matched for one request.

📱 How to Test

Tests added testing various behavior.
No changes to existing tests verify that we don't have any behavior change.

In the original code, the requests list/queue is processed when new requests are executed. And earlier mocks are removed on-the-fly when hiroaki responds. It is actually not possible to compare and remove previous matchers immediately when they're added since they don't implement `equals` functionality.

With this approach here is some principles I put into place:

- Regular `respond` always takes priority regardless of being added before or after.
- The most recently added `respondForever` takes precedence. As mentioned above, I cannot clear previous matchers immediately when a new one is added. I could potentially clear previous one when a `respondForever` is matched successfully. I figured that this is not a good idea since 1. it is not trivial, 2. there might be cases where previously added matcher can be useful for other requests even though it is matched for one request.
dataSource.getNews()
}

server.verify("v2/top-headlines").called()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test should verify that error is returned on first call, then success with the provided body for subsequent calls. We're just verifying that the endpoint is called here 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a single call here. So no error at all. I want to demonstrate the behavior where calling it The 2nd times overrides the existing. So error is ignored.

Copy link
Owner

@JorgeCastilloPrz JorgeCastilloPrz Feb 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect this to return error on a first match, then subsequent calls would return the provided success forever 🤔 that's what "then" wording leads to understand and I'd like to achieve.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. Could it be fine to come up with different naming?

Calling forever 2nd time should override the first. This makes it fundamentally different than the original behavior. Let me think about it more and how this can be made obvious.

If you can think of any alternative, it would be awesome.

Copy link
Owner

@JorgeCastilloPrz JorgeCastilloPrz Mar 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the naming is great and I like the feature, I'd aim for matching the behaviour I describe. That would make it coherent, as in living up to the "then" prefix for ordering matched / dispatched requests. That's what makes the whole thing very idiomatic on usage, imho. As you say, making it "obvious".

My expectations for this feature would be:

  • If you add any number of thenRespond before thenRespondForever, those must be matched first and removed. thenRespondForever does not get removed from the queue when matched / dispatched, so it can keep matching / dispatching.

  • As soon as a thenRespondForever is declared, further thenRespond calls declared after it would have no effect. This would be clarified in docs, since thenRespondForever has a wider priority given to its own semantics. It's "forever".

  • Same for multiple calls to thenRespondForever, I'd suggest matching just for the first one found on the queue so it matches previous behaviour also.

  • We can add an additional resetQueue param to thenRespond and thenRespondForever (same for the dispatch variants) so you can reset the queue and your newly added matcher becomes the first one in the queue. That would be used for cases where you want to assert multiple scenarios under the same test. In my opinion it's always better to write different tests for this, so they're atomic in terms of error reporting once they start failing. Still it's fine to provide this feature for flexibility imho, since every project has different requirements and people uses to work in many different ways, so I'd rather not being super opinionated on this. Some scenario for the sake of the example:

    • User configures matchers for one request, one thenRespond(), one thenRespondForever().
    • thenRespond() gets matched when first endpoint call occurs, user verifies.
    • 3 more endpoint calls occur, thenRespondForever() is matched for all those. User verifies.
    • Then user decides she/he wants to queue a new thenRespond() (or a new thenRespondForever()) and make further calls, then verify. The user could use the resetQueue param for this. resetQueue param would be defaulted to false.

Thoughts? Do you see any flaws? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for super late reply. I think I will give it another go.

I think this is going to be very difficult because technically, it is impossible to compare matchers.

Imagine a scenario where thenRespond and thenRespondForever has slightly different matchers matching the same request. This also depends on the request, that's why all should be recorded and then decided at the time of the actual request.

Queue logic is much easier since they are processed and removed sequentially.

If you already have an idea on the data structure, please let me know. I think I will first right the tests according to these expectations. And then see how we can do this.

dataSource.getNews()
}

server.verify("v2/top-headlines").called()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, we should verify the second one is the one responded for N calls and the first one is ignored

dataSource.getNews()
}

server.verify("v2/top-headlines").called()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be verifying what's required here?

@tasomaniac tasomaniac closed this Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for thenRespondForever
2 participants