diff --git a/Docs/pages/04-verify-interactions.md b/Docs/pages/04-verify-interactions.md index 68581345..721063f7 100644 --- a/Docs/pages/04-verify-interactions.md +++ b/Docs/pages/04-verify-interactions.md @@ -18,6 +18,22 @@ Supported call count verifications in the `Mockolate.VerifyMock` namespace: - `.Between(min, max)`: The interaction occurred between min and max times (inclusive) - `.Times(predicate)`: The interaction count matches the predicate +If the invocations run in a background thread, you can use `Within(TimeSpan)` to specify a timeout in which to wait for +the expected interactions to occur: + +```csharp +// Wait up to 1 second for Dispense("Dark", 5) to be invoked +sut.VerifyMock.Invoked.Dispense(It.Is("Dark"), It.Is(5)) + .Within(TimeSpan.FromSeconds(1)) + .AtLeastOnce(); +``` + +You can also use `WithCancellation(CancellationToken)` to wait for the expected interactions until the cancellation +token is canceled. If you combine this with the `Within` method, both the timeout and the cancellation token are respected. + +In both cases, it will block the test execution until the expected interaction occurs or the timeout is reached. +If the interaction does not occur within the specified time, a `MockVerificationException` will be thrown. + ## Properties You can verify access to property getter and setter: @@ -59,6 +75,14 @@ sut.VerifyMock.Invoked.Dispense(It.IsAny(), It.IsAny()) .Times(count => count % 2 == 0); ``` +You can also verify that a specific setup was invoked a specific number of times: + +```csharp +var setup = sut.SetupMock.Method.Dispense(It.Is("Dark"), It.Is(5)).Returns(true); +// Act +sut.VerifyMock.InvokedSetup(setup).AtLeastOnce(); +``` + ## Indexers You can verify access to indexer getter and setter: diff --git a/Docs/pages/special-types/01-httpclient.md b/Docs/pages/special-types/01-httpclient.md index 0d6b0f95..16b1a98b 100644 --- a/Docs/pages/special-types/01-httpclient.md +++ b/Docs/pages/special-types/01-httpclient.md @@ -243,3 +243,31 @@ httpClient.SetupMock.Method - By default, only the content headers are checked, not the headers in the corresponding `HttpRequestMessage`. If you want to check both, add the `.IncludingRequestHeaders()` modifier. + +## Return Message + +Overloads of `.ReturnsAsync` simplify specifying the return value for HTTP method setups. + +```csharp +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and no content + .ReturnsAsync(HttpStatusCode.OK); + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a string content "some string content" + .ReturnsAsync(HttpStatusCode.OK, "some string content"); + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a JSON content {"foo":"bar"} + .ReturnsAsync(HttpStatusCode.OK, "{\"foo\":\"bar\"}", "application/json"); + +byte[] bytes = new byte[] { /* ... */ }; + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a binary content with the provided bytes + .ReturnsAsync(HttpStatusCode.OK, bytes); + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a PNG image content with the provided bytes + .ReturnsAsync(HttpStatusCode.OK, bytes, "image/png"); +``` diff --git a/README.md b/README.md index 0b50ccd8..f6052acb 100644 --- a/README.md +++ b/README.md @@ -644,6 +644,22 @@ Supported call count verifications in the `Mockolate.VerifyMock` namespace: - `.Between(min, max)`: The interaction occurred between min and max times (inclusive) - `.Times(predicate)`: The interaction count matches the predicate +If the invocations run in a background thread, you can use `Within(TimeSpan)` to specify a timeout in which to wait for +the expected interactions to occur: + +```csharp +// Wait up to 1 second for Dispense("Dark", 5) to be invoked +sut.VerifyMock.Invoked.Dispense(It.Is("Dark"), It.Is(5)) + .Within(TimeSpan.FromSeconds(1)) + .AtLeastOnce(); +``` + +You can also use `WithCancellation(CancellationToken)` to wait for the expected interactions until the cancellation +token is canceled. If you combine this with the `Within` method, both the timeout and the cancellation token are respected. + +In both cases, it will block the test execution until the expected interaction occurs or the timeout is reached. +If the interaction does not occur within the specified time, a `MockVerificationException` will be thrown. + ### Properties You can verify access to property getter and setter: @@ -685,6 +701,14 @@ sut.VerifyMock.Invoked.Dispense(It.IsAny(), It.IsAny()) .Times(count => count % 2 == 0); ``` +You can also verify that a specific setup was invoked a specific number of times: + +```csharp +var setup = sut.SetupMock.Method.Dispense(It.Is("Dark"), It.Is(5)).Returns(true); +// Act +sut.VerifyMock.InvokedSetup(setup).AtLeastOnce(); +``` + ### Indexers You can verify access to indexer getter and setter: @@ -1225,6 +1249,34 @@ httpClient.SetupMock.Method - By default, only the content headers are checked, not the headers in the corresponding `HttpRequestMessage`. If you want to check both, add the `.IncludingRequestHeaders()` modifier. +#### Return Message + +Overloads of `.ReturnsAsync` simplify specifying the return value for HTTP method setups. + +```csharp +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and no content + .ReturnsAsync(HttpStatusCode.OK); + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a string content "some string content" + .ReturnsAsync(HttpStatusCode.OK, "some string content"); + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a JSON content {"foo":"bar"} + .ReturnsAsync(HttpStatusCode.OK, "{\"foo\":\"bar\"}", "application/json"); + +byte[] bytes = new byte[] { /* ... */ }; + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a binary content with the provided bytes + .ReturnsAsync(HttpStatusCode.OK, bytes); + +httpClient.SetupMock.Method.GetAsync(It.IsAny()) + // Returns a response with status code 200 OK and a PNG image content with the provided bytes + .ReturnsAsync(HttpStatusCode.OK, bytes, "image/png"); +``` + ### Delegates Mockolate supports mocking delegates including `Action`, `Func`, and custom delegates.