Skip to content

Serve the exact-matching mock instead of a partial match - #912

Open
eastagiletracker wants to merge 1 commit into
virtualansoftware:masterfrom
eastagiletracker:agile-board/serve-exact-mock-match
Open

eastagiletracker wants to merge 1 commit into
virtualansoftware:masterfrom
eastagiletracker:agile-board/serve-exact-mock-match

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes serving the exact-matching mock instead of a partial match when a virtualized API picks its response. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/710. You can sign in with your GitHub ID to claim ownership of the project.

What was wrong

When a request fully matches one mock and only partially matches another mock that matched more params, the plugin can serve the partial one. Example: mock A has status=available, mock B has status=available&tag=x&name=q, and the request is ?status=available&tag=x. A is the exact match (1 of 1 params), B is a partial match (2 of 3). VirtualServiceUtil.returnResponse checks that an exact match exists, but then getResponse serves the head of the list sorted by BestMatchComparator, and that comparator is not antisymmetric: compare(A, B) and compare(B, A) both return -1, so the sort just reverses the two and B can come out first. The mocks are collected in a HashMap keyed by MockRequest, whose Lombok hashCode goes through identity-hashed values (VirtualServiceKeyValue has no hashCode, and the enum field), so which mock wins can change from one load to the next.

The change

  • BestMatchComparator now defines a consistent order: mocks whose every param matched come first, then more matched params before fewer. Ties keep their original order.
  • returnResponse serves the first exact match from the sorted list instead of the list head, because an exact match does not always sort first (e.g. an exact match on a request with no params carries no param count). The existing public getResponse(Method, List) still serves the head of the list and now delegates to a new getResponse(Method, ReturnMockResponse) overload, so existing callers behave the same.

Reproduction and verification

The module had no tests, so this adds VirtualServiceUtilTest and BestMatchComparatorTest (JUnit 5 and Mockito from the existing spring-boot-starter-test dependency). servesExactMatchThroughRealMatcher drives the real VirtualServiceValidRequest and VirtualServiceParamComparator with only VirtualService mocked, and repeats the request against freshly loaded mocks. On current master (bdbcae6) with the new tests and no fix, mvn -B verify fails:

[ERROR]   VirtualServiceUtilTest.servesExactMatchThroughRealMatcher:210 attempt 0 ==> expected: <exact> but was: <partial>
[ERROR]   VirtualServiceUtilTest.servesExactMatchWhenPartialMatchComesSecond:113 expected: <exact> but was: <partial>
[ERROR]   BestMatchComparatorTest.isAntisymmetric:46 general vs partial ==> expected: <-1> but was: <1>
[ERROR] Tests run: 11, Failures: 5, Errors: 0, Skipped: 0

With only the comparator fix applied, servesExactMatchThatHasNoParamsAheadOfPartialMatch still fails (expected: <exact> but was: <partial>), so each half of the change has a test that needs it. With both changes, mvn -B verify on JDK 17 passes: Tests run: 11, Failures: 0, Errors: 0, Skipped: 0, BUILD SUCCESS. The baseline build of the untouched tree was also green (it had no tests to run). The tests also cover the not-found path when no mock matches exactly and the most specific exact match winning in every input order. One side effect worth knowing about: the duplicate check in isMockAlreadyExists also sorts with BestMatchComparator, so it now checks the full match first too.

How this was managed

This work is tracked as a story on a board imported from this repository's issues and pull requests (911 stories): https://eastagiletracker.com/projects/710/stories/653353 on the board https://eastagiletracker.com/projects/710.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

BestMatchComparator was not antisymmetric, so a partial match with more
matched params could sort ahead of an exact match, and returnResponse
served the head of the sorted list even when it was not the exact match.
Rank full matches first, then by matched param count, and serve the
first exact match.
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.

1 participant