[Prototype] Task 2/6 via Kestrel-hosted fake-API controllers (compare vs #129, #130)#131
Draft
elahmed-microsoft wants to merge 11 commits into
Draft
[Prototype] Task 2/6 via Kestrel-hosted fake-API controllers (compare vs #129, #130)#131elahmed-microsoft wants to merge 11 commits into
elahmed-microsoft wants to merge 11 commits into
Conversation
Add the WireMock.Net package reference and lock-file entries; it provides the in-process HTTP mock server used to build the Ingestion and XFUS fixtures in later phases. The package is saved to the private feed and is publicly readable, so CI restores it without authentication.
Add IngestionMockServer, a reusable WireMock.Net-backed fake of the Partner Center Ingestion API with fluent stubs for the endpoints PackageUploader uses (GetProduct, GetBranches, CreatePackage, package processing poll, package configuration, CreateSubmission, submission poll) and configurable success/error/retry/polling scenarios. Polling and retry use WireMock stateful scenarios with self-looping terminal states.
Add XfusMockServer, a reusable WireMock.Net-backed fake of the XFUS upload service serving the three-step chunked upload (initialize, block payload PUT, continue) rooted at /api/v2/assets/. Omits directUploadParameters.sasUri so the client uses the proxy PUT path, and emits the upload status as a number to match the client serializer. Provides a no-delta success convenience plus initialize/block/continue primitives and stateful continue-progression and block-retry scenarios.
…se 3) Add MockServerTestHost, which owns the Ingestion and XFUS WireMock fakes and composes the real IPackageUploaderService pointed at them (Ingestion via IngestionConfig:BaseAddress, XFUS via the upload domain returned in the package response), keeping FakeAccessTokenProvider. Extend IngestionMockServer.StubCreatePackage to embed the XFUS upload info, and add IntegrationTestBase.CreateMockServerHost().
Remove the superseded in-process PackageUploaderTestHost and MockHttpMessageHandler, migrate the smoke test to CreateMockServerHost() (real HTTP to the WireMock Ingestion fake), and drop the CreateHost overload. MockServerTestHost is now the single canonical integration test host.
…Task 2/6 Phase 4) Add IngestionApiTests (success, NotFound, transient-error retry, branches), UploadFlowTests (full no-delta upload tying the Ingestion and XFUS fakes together), and PublishFlowTests (submission create + poll to Published). Enhance IngestionMockServer with submission pendingUpdateInfo (mapper NRE guard), package-config market group, StubProcessPackage, and a flights stub; add fast retry config to MockServerTestHost.
- IngestionMockServer: emit null (not an empty object) for absent uploadInfo so the client's Guid mapping doesn't throw on a null XfusId; short-circuit StubRetryThenSuccess(failures<=0) to an unconditional success instead of an unmatched 404. - XfusMockServer: short-circuit StubBlockUploadRetryThenSuccess(failures<=0); document the single-asset-per-server assumption of StubContinueProgression. - MockServerTestHost: dispose the WireMock servers if composition throws, to avoid leaking listeners. - UploadFlowTests: assert a block payload PUT actually reached XFUS rather than any request.
…pp (controllers) Replace WireMock.Net with a first-party fake-API ASP.NET Core app: IngestionController and XfusController mirror the routes the client calls and delegate to per-test scenario stores; the host boots them on a random loopback port via Kestrel and points the real client at it (real sockets, real SocketsHttpHandler). Uses only the Microsoft.AspNetCore.App shared framework (FrameworkReference) -- zero NuGet packages, so locked-mode restore needs no feed provisioning. Same 7 integration tests pass.
- MockServerTestHost: dispose the Kestrel app if composition throws after StartAsync, to avoid leaking a listener. - FakeApiControllerBase: record binary (octet-stream) request bodies as a size marker instead of a lossy UTF-8 text read. - IngestionScenarioStore: include marketGroupPackages in the package-configuration paged list so the already-initialized path is exercised; default StubProcessPackage state to Processed and document that it (not the poll) drives the returned state. - UploadFlowTests: assert the package processing poll GET was issued so the polling stub is load-bearing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose: comparison prototype (do not merge as-is)
A third implementation of Task 2/6, for side-by-side comparison with #129 (WireMock.Net) and #130 (in-memory HttpMessageHandler). This implements Anthony's suggestion: host controllers that present themselves as the Ingestion/XFUS APIs and point the client's service-URI config at them. Same 7 integration tests, all passing.
Approach: Kestrel-hosted fake-API app (first-party)
A small ASP.NET Core app with controllers mirroring the routes the client calls, hosted on a random loopback port via Kestrel; the real client is pointed at it via
IngestionConfig:BaseAddress.IngestionController/XfusController— present theproducts/...andapi/v2/assets/...route spaces and delegate to per-test scenario stores.IngestionScenarioStore/XfusScenarioStore— same fluent stub API as the other prototypes (StubGetProduct,StubNoDeltaUploadSuccess, retry/polling, errors); records requests for assertions.MockServerTestHost— boots the fake app, points the client at it, keepsFakeAccessTokenProvider.A note on TestServer vs Kestrel
Anthony said "TestServer + localhost+port".
TestServeritself is in-memory (no real port) and needs theMicrosoft.AspNetCore.TestHostpackage. To honor the literal "localhost+port + config" wording and keep real-socket fidelity and avoid any NuGet package, I hosted the same fake app on Kestrel using only<FrameworkReference Include="Microsoft.AspNetCore.App" />(ships with the SDK). Swapping to in-memory TestServer is a trivial change if preferred.Only Ingestion needs the config override; XFUS is reached via the
uploadDomainreturned in the fake package response.Three-way comparison
Where it lands
This is the most faithful and highest-fidelity first-party option: it's a real HTTP server with real routing/controllers, exercises the client's real sockets (matching WireMock), and needs no third-party package or feed provisioning (matching #130). The cost is the most code — a small fake-API app to maintain.
Verification
dotnet buildclean;dotnet restore --locked-modepasses with no new packages (the exact step failing on Task 2/6: Mock HTTP server infrastructure for Ingestion API and XFUS #129).Recommendation
Pick based on priorities: #131 if you want a realistic, first-party fake service with real-socket fidelity (most code); #130 if you want the lightest first-party option (no real socket); #129 if the built-in scenario DSL is worth the third-party dependency + feed overhead.