From 3826dfbddd74a977e15f6ddd6b4b18abb7385030 Mon Sep 17 00:00:00 2001 From: gparmigiani Date: Mon, 16 Dec 2024 16:52:33 +0100 Subject: [PATCH 1/3] Add test for no mocks declared exception * Add a check for `PrimaryHandler` being null in the `MockClientHandler` class. * Throw a new exception with the message "no mocks were provided" if `PrimaryHandler` is null. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/jkone27/fsharp-integration-tests?shareId=XXXX-XXXX-XXXX-XXXX). --- .devcontainer/devcontainer.json | 6 +++++ ApiStub.FSharp/CE.fs | 21 ++++++++++++++- test/ApiStub.FSharp.Tests.fsproj | 3 ++- test/Issues.fs | 44 ++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 test/Issues.fs diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..2d5484b --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,6 @@ +{ + "tasks": { + "test": "dotnet test", + "build": "dotnet build" + } +} \ No newline at end of file diff --git a/ApiStub.FSharp/CE.fs b/ApiStub.FSharp/CE.fs index af95135..f4bc1b8 100644 --- a/ApiStub.FSharp/CE.fs +++ b/ApiStub.FSharp/CE.fs @@ -199,4 +199,23 @@ module CE = |> ignore ) - + type MockClientHandler(handler : HttpMessageHandler, methods, templateMatcher: TemplateMatcher, responseStubber) = + inherit DelegatingHandler(handler) + + override this.SendAsync(request, token) = + let wrappedBase = new AsyncCallableHandler(base.InnerHandler) + task { + let routeDict = new RouteValueDictionary() + if methods |> Array.contains(request.Method) |> not then + return! wrappedBase.CallSendAsync(request, token) + else if templateMatcher.TryMatch(request.RequestUri.AbsolutePath |> PathString, routeDict) |> not then + return! wrappedBase.CallSendAsync(request, token) + else + if base.InnerHandler = null then + raise (InvalidOperationException("no mocks were provided")) + // HTTP response stubbing happens here, the request has matched, go on with the stub + let! (expected : HttpResponseMessage) = responseStubber request routeDict + // reattach original request!!! + expected.RequestMessage <- request + return expected + } diff --git a/test/ApiStub.FSharp.Tests.fsproj b/test/ApiStub.FSharp.Tests.fsproj index 9faceeb..1b7f518 100644 --- a/test/ApiStub.FSharp.Tests.fsproj +++ b/test/ApiStub.FSharp.Tests.fsproj @@ -9,6 +9,7 @@ + @@ -34,4 +35,4 @@ - \ No newline at end of file + diff --git a/test/Issues.fs b/test/Issues.fs new file mode 100644 index 0000000..a3a1f83 --- /dev/null +++ b/test/Issues.fs @@ -0,0 +1,44 @@ +namespace ApiStub.FSharp.Tests + +open Xunit +open fsharpintegrationtests +open Microsoft.AspNetCore.Mvc.Testing +open Microsoft.Extensions.DependencyInjection +open Microsoft.AspNetCore.Hosting +open SwaggerProvider +open System.Threading.Tasks +open System.Net.Http +open System +open Microsoft.AspNetCore.TestHost +open Microsoft.Extensions.Http +open Microsoft.AspNetCore.Routing.Template +open Microsoft.AspNetCore.Routing.Patterns +open Microsoft.AspNetCore.Routing +open System.Net +open System.Text.Json +open Microsoft.AspNetCore.Http +open System.Net.Http.Json +open Swensen.Unquote +open ApiStub.FSharp.CE +open ApiStub.FSharp.BuilderExtensions +open ApiStub.FSharp.HttpResponseHelpers +open ApiStub.FSharp +open ApiStub.FSharp.BDD +open HttpResponseMessageExtensions +open Xunit.Abstractions + +module IssuesTests = + + let testce = new CE.TestClient() + + [] + let ``test_no_mocks_declared_throws_exception`` () = + task { + let factory = testce.GetFactory() + let client = factory.CreateClient() + + let! response = client.GetAsync("/Hello") + Assert.False(response.IsSuccessStatusCode) + let! responseString = response.Content.ReadAsStringAsync() + Assert.Contains("no mocks were provided", responseString) + } From f1501bce237c9406f6cbfbe115a8ab5d699cf2ad Mon Sep 17 00:00:00 2001 From: gparmigiani Date: Mon, 16 Dec 2024 16:59:36 +0100 Subject: [PATCH 2/3] --- ApiStub.FSharp/CE.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/ApiStub.FSharp/CE.fs b/ApiStub.FSharp/CE.fs index f4bc1b8..9269bb2 100644 --- a/ApiStub.FSharp/CE.fs +++ b/ApiStub.FSharp/CE.fs @@ -8,6 +8,7 @@ open System open Microsoft.Extensions.Http open Microsoft.AspNetCore.Routing.Template open Microsoft.AspNetCore.Routing +open Microsoft.AspNetCore.Http module CE = open BuilderExtensions From a2e5b6661c9b85fd2f4a67ebda81a24e72774e36 Mon Sep 17 00:00:00 2001 From: gparmigiani Date: Sat, 10 May 2025 12:45:49 +0200 Subject: [PATCH 3/3] add check for no mocks --- ApiStub.FSharp/CE.fs | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/ApiStub.FSharp/CE.fs b/ApiStub.FSharp/CE.fs index 118c4ae..589a695 100644 --- a/ApiStub.FSharp/CE.fs +++ b/ApiStub.FSharp/CE.fs @@ -212,6 +212,10 @@ module CE = s.ConfigureAll(fun options -> options.HttpMessageHandlerBuilderActions.Add(fun builder -> //builder.AdditionalHandlers.Add(httpMessageHandler) |> ignore + + if httpMessageHandler = null then + failwith "no mocks were provided" + builder.PrimaryHandler <- httpMessageHandler) options.HttpClientActions.Add(fun c -> @@ -233,29 +237,3 @@ module CE = |> web_configure_test_services (fun s -> for custom_config in customConfigureTestServices do custom_config (s) |> ignore) - - type MockClientHandler(handler: HttpMessageHandler, methods, templateMatcher: TemplateMatcher, responseStubber) = - inherit DelegatingHandler(handler) - - override this.SendAsync(request, token) = - let wrappedBase = new AsyncCallableHandler(base.InnerHandler) - - task { - let routeDict = new RouteValueDictionary() - - if (methods |> Array.contains (request.Method) |> not) then - return! wrappedBase.CallSendAsync(request, token) - else if - (templateMatcher.TryMatch(request.RequestUri.AbsolutePath |> PathString, routeDict) - |> not) - then - return! wrappedBase.CallSendAsync(request, token) - else - if (this.InnerHandler = null) then - raise (InvalidOperationException("no mocks were provided")) - // HTTP response stubbing happens here, the request has matched, go on with the stub - let! (expected: HttpResponseMessage) = responseStubber request routeDict - // reattach original request!!! - expected.RequestMessage <- request - return expected - }