diff --git a/src/MockHttp.Json/SystemTextJson/JsonDocumentEqualityComparer.cs b/src/MockHttp.Json/SystemTextJson/JsonDocumentEqualityComparer.cs index 796e1879..c40c5c03 100644 --- a/src/MockHttp.Json/SystemTextJson/JsonDocumentEqualityComparer.cs +++ b/src/MockHttp.Json/SystemTextJson/JsonDocumentEqualityComparer.cs @@ -51,7 +51,7 @@ private static bool ElemEquals(JsonElement left, JsonElement right, JsonSerializ JsonValueKind.False => true, JsonValueKind.True => true, JsonValueKind.String => left.ValueEquals(right.GetString()), - JsonValueKind.Number => left.GetRawText().Equals(right.GetRawText()), + JsonValueKind.Number => string.Equals(left.GetRawText(), right.GetRawText(), StringComparison.Ordinal), JsonValueKind.Array => ArrayEquals(left, right, serializerOptions), JsonValueKind.Object => ObjectEquals(left, right, serializerOptions), _ => false diff --git a/src/MockHttp.Json/SystemTextJson/SystemTextJsonEqualityComparer.cs b/src/MockHttp.Json/SystemTextJson/SystemTextJsonEqualityComparer.cs index f18d684d..290df4db 100644 --- a/src/MockHttp.Json/SystemTextJson/SystemTextJsonEqualityComparer.cs +++ b/src/MockHttp.Json/SystemTextJson/SystemTextJsonEqualityComparer.cs @@ -51,6 +51,10 @@ public bool Equals(string? x, string? y) public int GetHashCode(string obj) { +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return obj.GetHashCode(StringComparison.Ordinal); +#else return obj.GetHashCode(); +#endif } } diff --git a/src/MockHttp.Server/MockHttpServer.cs b/src/MockHttp.Server/MockHttpServer.cs index 2b49a1b3..da13c410 100644 --- a/src/MockHttp.Server/MockHttpServer.cs +++ b/src/MockHttp.Server/MockHttpServer.cs @@ -23,7 +23,7 @@ public sealed class MockHttpServer : IDisposable [DebuggerBrowsable(DebuggerBrowsableState.Never)] private IWebHost? _host; [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private readonly string _hostUrl; + private readonly Uri _hostUri; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private Action? _configureAppBuilder; @@ -32,8 +32,19 @@ public sealed class MockHttpServer : IDisposable /// /// The mock http handler. /// The host URL the mock HTTP server will listen on. + [Obsolete("Use the overload accepting an System.Uri.")] public MockHttpServer(MockHttpHandler mockHttpHandler, string hostUrl) - : this(mockHttpHandler, null, hostUrl) + : this(mockHttpHandler, GetHostUrl(hostUrl)) + { + } + + /// + /// Initializes a new instance of the using specified and configures it to listen on specified . + /// + /// The mock http handler. + /// The host URI the mock HTTP server will listen on. + public MockHttpServer(MockHttpHandler mockHttpHandler, Uri hostUri) + : this(mockHttpHandler, null, hostUri) { } @@ -43,12 +54,24 @@ public MockHttpServer(MockHttpHandler mockHttpHandler, string hostUrl) /// The mock http handler. /// The logger factory to use to log pipeline requests to. /// The host URL the mock HTTP server will listen on. + [Obsolete("Use the overload accepting an System.Uri.")] public MockHttpServer(MockHttpHandler mockHttpHandler, ILoggerFactory? loggerFactory, string hostUrl) + : this(mockHttpHandler, loggerFactory, GetHostUrl(hostUrl)) + { + } + + /// + /// Initializes a new instance of the using specified and configures it to listen on specified . + /// + /// The mock http handler. + /// The logger factory to use to log pipeline requests to. + /// The host URI the mock HTTP server will listen on. + public MockHttpServer(MockHttpHandler mockHttpHandler, ILoggerFactory? loggerFactory, Uri hostUri) { Handler = mockHttpHandler ?? throw new ArgumentNullException(nameof(mockHttpHandler)); _webHostBuilder = CreateWebHostBuilder(loggerFactory); - _hostUrl = GetHostUrl(hostUrl); - _webHostBuilder.UseUrls(_hostUrl); + _hostUri = new Uri(hostUri, "/"); // Ensure base URL. + _webHostBuilder.UseUrls(_hostUri.ToString()); } /// @@ -66,13 +89,24 @@ public void Dispose() /// /// Gets the host URL the mock HTTP server will listen on. /// - public string HostUrl + [Obsolete("Use the HostUri instead.")] +#pragma warning disable CA1056 // URI-like properties should not be strings + public string HostUrl => HostUri.ToString().TrimEnd('/'); +#pragma warning restore CA1056 // URI-like properties should not be strings + + /// + /// Gets the host URI the mock HTTP server will listen on. + /// + public Uri HostUri { get { lock (_syncLock) { - return _host?.ServerFeatures.Get()?.Addresses.First() ?? _hostUrl; + string? url = _host?.ServerFeatures.Get()?.Addresses.First(); + return url is null + ? _hostUri + : new Uri(url); } } } @@ -140,7 +174,7 @@ public Task StopAsync(CancellationToken cancellationToken = default) /// public HttpClient CreateClient() { - return new HttpClient { BaseAddress = new Uri(HostUrl) }; + return new HttpClient { BaseAddress = HostUri }; } private IWebHostBuilder CreateWebHostBuilder(ILoggerFactory? loggerFactory) @@ -173,20 +207,16 @@ internal void Configure(Action configureAppBuilder) _configureAppBuilder = configureAppBuilder; } - private static string GetHostUrl(string hostUrl) + private static Uri GetHostUrl(string hostUrl) { if (hostUrl is null) { throw new ArgumentNullException(nameof(hostUrl)); } - if (!Uri.TryCreate(hostUrl, UriKind.Absolute, out Uri? uri)) - { - throw new ArgumentException(Resources.Error_HostUrlIsNotValid, nameof(hostUrl)); - } - - // Ensure we have a proper host URL without path/query. - return $"{uri.Scheme}://{uri.Host}:{uri.Port}"; + return Uri.TryCreate(hostUrl, UriKind.Absolute, out Uri? uri) + ? uri + : throw new ArgumentException(Resources.Error_HostUrlIsNotValid, nameof(hostUrl)); } private void AddMockHttpServerHeader(IApplicationBuilder applicationBuilder) diff --git a/src/MockHttp.Server/Server/ServerRequestHandler.cs b/src/MockHttp.Server/Server/ServerRequestHandler.cs index ec5665ea..1cbbd8d3 100644 --- a/src/MockHttp.Server/Server/ServerRequestHandler.cs +++ b/src/MockHttp.Server/Server/ServerRequestHandler.cs @@ -42,7 +42,9 @@ public async Task HandleAsync(HttpContext httpContext, Func _) { LogRequestMessage(httpContext, Resources.Error_VerifyMockSetup); +#pragma warning disable CA2000 // Dispose objects before losing scope httpResponseMessage = new HttpResponseMessage(HttpStatusCode.InternalServerError) +#pragma warning restore CA2000 // Dispose objects before losing scope { ReasonPhrase = Resources.Error_VerifyMockSetup, Content = new StringContent(Resources.Error_VerifyMockSetup + Environment.NewLine + ex, MockHttpHandler.DefaultEncoding, MediaTypes.PlainText) diff --git a/src/MockHttp/Extensions/ResponseBuilderExtensions.cs b/src/MockHttp/Extensions/ResponseBuilderExtensions.cs index 3b946e1f..b1937b48 100644 --- a/src/MockHttp/Extensions/ResponseBuilderExtensions.cs +++ b/src/MockHttp/Extensions/ResponseBuilderExtensions.cs @@ -201,7 +201,7 @@ public static IWithContentResult Body(this IWithContent builder, Func { - Stream stream = await streamContentFactory(token); + Stream stream = await streamContentFactory(token).ConfigureAwait(false); if (!stream.CanRead) { throw new InvalidOperationException("Cannot read from stream."); diff --git a/src/MockHttp/Http/DataEscapingHelper.cs b/src/MockHttp/Http/DataEscapingHelper.cs index 18fd04ea..4feeb518 100644 --- a/src/MockHttp/Http/DataEscapingHelper.cs +++ b/src/MockHttp/Http/DataEscapingHelper.cs @@ -50,7 +50,11 @@ internal static IEnumerable>> Parse(str private static string UnescapeData(string v) { - return Uri.UnescapeDataString(v?.Replace("+", "%20")!); + return Uri.UnescapeDataString(v?.Replace("+", "%20" +#if NET7_0_OR_GREATER || NETSTANDARD2_1 + , StringComparison.Ordinal +#endif + )!); } internal static string Format(IEnumerable> items) diff --git a/src/MockHttp/Http/HttpHeadersCollection.cs b/src/MockHttp/Http/HttpHeadersCollection.cs index 460d01c8..9d32fdfc 100644 --- a/src/MockHttp/Http/HttpHeadersCollection.cs +++ b/src/MockHttp/Http/HttpHeadersCollection.cs @@ -4,6 +4,9 @@ namespace MockHttp.Http; internal sealed class HttpHeadersCollection : HttpHeaders { + private static readonly char[] HeaderKeyValueSeparator = new[] { ':' }; + private static readonly char[] HeaderValueSeparator = new[] { ',' }; + public HttpHeadersCollection() { } @@ -43,7 +46,7 @@ public static HttpHeaders Parse(string headers) continue; } - string[] hvp = header.Split(new[] { ':' }, 2, StringSplitOptions.None); + string[] hvp = header.Split(HeaderKeyValueSeparator, 2, StringSplitOptions.None); string fieldName = hvp.Length > 0 ? hvp[0] : string.Empty; string? fieldValue = hvp.Length > 1 ? hvp[1] : null; @@ -61,7 +64,7 @@ internal static IEnumerable ParseHttpHeaderValue(string? headerValue) } return headerValue - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Split(HeaderValueSeparator, StringSplitOptions.RemoveEmptyEntries) .Select(v => v.Trim()) .Where(v => v.Length > 0) .ToArray(); diff --git a/src/MockHttp/Matchers/ContentMatcher.cs b/src/MockHttp/Matchers/ContentMatcher.cs index 84f61edc..e42e576e 100644 --- a/src/MockHttp/Matchers/ContentMatcher.cs +++ b/src/MockHttp/Matchers/ContentMatcher.cs @@ -47,7 +47,7 @@ public ContentMatcher(byte[] content) /// Gets the expected content in bytes. /// // ReSharper disable once MemberCanBeProtected.Global - protected internal byte[] ByteContent { get; } + protected internal IReadOnlyList ByteContent { get; } /// public Task IsMatchAsync(MockHttpRequestContext requestContext) @@ -71,10 +71,10 @@ async Task InternalIsMatchAsync(MockHttpRequestContext mockHttpRequestCont if (requestContent is null) { - return ByteContent.Length == 0; + return ByteContent.Count == 0; } - if (requestContent.Length == 0 && ByteContent.Length == 0) + if (requestContent.Length == 0 && ByteContent.Count == 0) { return true; } @@ -99,17 +99,17 @@ protected virtual bool IsMatch(byte[] requestContent) /// public override string ToString() { - if (ByteContent.Length == 0) + if (ByteContent.Count == 0) { return "Content: "; } if (_encoding is not null) { - return $"Content: {_encoding.GetString(ByteContent, 0, ByteContent.Length)}"; + return $"Content: {_encoding.GetString((byte[])ByteContent, 0, ByteContent.Count)}"; } - int charsToOutput = Math.Min(MaxBytesDisplayed, ByteContent.Length); + int charsToOutput = Math.Min(MaxBytesDisplayed, ByteContent.Count); var sb = new StringBuilder(); sb.Append("Content: ["); for (int i = 0; i < charsToOutput; i++) @@ -121,9 +121,9 @@ public override string ToString() } } - if (charsToOutput < ByteContent.Length) + if (charsToOutput < ByteContent.Count) { - sb.AppendFormat(CultureInfo.InvariantCulture, ",...](Size = {0})", ByteContent.Length); + sb.AppendFormat(CultureInfo.InvariantCulture, ",...](Size = {0})", ByteContent.Count); } else { diff --git a/src/MockHttp/Matchers/PartialContentMatcher.cs b/src/MockHttp/Matchers/PartialContentMatcher.cs index 91f65fd3..2c849484 100644 --- a/src/MockHttp/Matchers/PartialContentMatcher.cs +++ b/src/MockHttp/Matchers/PartialContentMatcher.cs @@ -15,7 +15,7 @@ public class PartialContentMatcher : ContentMatcher public PartialContentMatcher(string content, Encoding? encoding) : base(content, encoding) { - if (ByteContent.Length == 0) + if (ByteContent.Count == 0) { throw new ArgumentException("Content can not be empty.", nameof(content)); } @@ -28,7 +28,7 @@ public PartialContentMatcher(string content, Encoding? encoding) public PartialContentMatcher(byte[] content) : base(content) { - if (ByteContent.Length == 0) + if (ByteContent.Count == 0) { throw new ArgumentException("Content can not be empty.", nameof(content)); } diff --git a/src/MockHttp/MockHttpHandler.cs b/src/MockHttp/MockHttpHandler.cs index 2d84a411..baf1575a 100644 --- a/src/MockHttp/MockHttpHandler.cs +++ b/src/MockHttp/MockHttpHandler.cs @@ -14,9 +14,9 @@ namespace MockHttp; /// public sealed class MockHttpHandler : HttpMessageHandler, IMockConfiguration { - private readonly ConcurrentCollection _setups; - private readonly HttpCall _fallbackSetup; - private readonly IDictionary _items; + private readonly ConcurrentCollection _setups = new(); + private readonly HttpCall _fallbackSetup = new(); + private readonly Dictionary _items = new(); private readonly ReadOnlyDictionary _readOnlyItems; /// @@ -29,12 +29,9 @@ public sealed class MockHttpHandler : HttpMessageHandler, IMockConfiguration /// public MockHttpHandler() { - _setups = new ConcurrentCollection(); InvokedRequests = new InvokedHttpRequestCollection(this); - _items = new Dictionary(); _readOnlyItems = new ReadOnlyDictionary(_items); - _fallbackSetup = new HttpCall(); Fallback = new FallbackRequestSetupPhrase(_fallbackSetup); Reset(); } @@ -241,7 +238,7 @@ public void VerifyNoOtherRequests() .Cast() .Where(r => !r.IsVerified) .ToList(); - if (!unverifiedRequests.Any()) + if (unverifiedRequests.Count == 0) { return; } @@ -270,7 +267,7 @@ private void Verify(IEnumerable verifiableSetups) var expectedInvocations = verifiableSetups .Where(setup => !setup.VerifyIfInvoked()) .ToList(); - if (!expectedInvocations.Any()) + if (expectedInvocations.Count == 0) { return; } diff --git a/src/MockHttp/NetworkLatency.cs b/src/MockHttp/NetworkLatency.cs index f032c3ed..3827ce7b 100644 --- a/src/MockHttp/NetworkLatency.cs +++ b/src/MockHttp/NetworkLatency.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using MockHttp.Threading; namespace MockHttp; @@ -17,7 +16,9 @@ public class NetworkLatency static NetworkLatency() { // Warmup so that actual simulated latency is more accurate. +#pragma warning disable CA5394 // Do not use insecure randomness - justification: not used in secure context Random.Next(); +#pragma warning restore CA5394 // Do not use insecure randomness } private NetworkLatency(Func factory, string name) @@ -111,7 +112,9 @@ private static NetworkLatency Between(int minMs, int maxMs, string name) return new NetworkLatency(() => { +#pragma warning disable CA5394 // Do not use insecure randomness - justification: not used in secure context double randomLatency = Random.Next(minMs, maxMs); +#pragma warning restore CA5394 return TimeSpan.FromMilliseconds(randomLatency); }, name); diff --git a/src/MockHttp/RequestMatching.cs b/src/MockHttp/RequestMatching.cs index 387ba63e..e38494a1 100644 --- a/src/MockHttp/RequestMatching.cs +++ b/src/MockHttp/RequestMatching.cs @@ -70,7 +70,7 @@ protected internal virtual void ValidateMatcher(IAsyncHttpRequestMatcher matcher .Where(m => m.GetType() == matcher.GetType()) .ToList(); - if ((matcher.IsExclusive && sameTypeMatchers.Any()) || (!matcher.IsExclusive && sameTypeMatchers.Any(m => m.IsExclusive))) + if ((matcher.IsExclusive && sameTypeMatchers.Count > 0) || (!matcher.IsExclusive && sameTypeMatchers.Any(m => m.IsExclusive))) { throw new InvalidOperationException($"Cannot add matcher, another matcher of type '{matcher.GetType().FullName}' already is configured."); } diff --git a/src/MockHttp/Responses/HttpHeaderBehavior.cs b/src/MockHttp/Responses/HttpHeaderBehavior.cs index 79cc07a3..daa96fc0 100644 --- a/src/MockHttp/Responses/HttpHeaderBehavior.cs +++ b/src/MockHttp/Responses/HttpHeaderBehavior.cs @@ -7,7 +7,7 @@ internal sealed class HttpHeaderBehavior : IResponseBehavior { //https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - private static readonly ISet HeadersWithSingleValueOnly = new HashSet + private static readonly HashSet HeadersWithSingleValueOnly = new() { // TODO: expand this list. HeaderNames.Age, diff --git a/src/MockHttp/Threading/ConcurrentCollection.cs b/src/MockHttp/Threading/ConcurrentCollection.cs index ebff2ba1..1534b5ba 100644 --- a/src/MockHttp/Threading/ConcurrentCollection.cs +++ b/src/MockHttp/Threading/ConcurrentCollection.cs @@ -76,7 +76,9 @@ public T this[int index] if (_items is null) { #pragma warning disable S112 +#pragma warning disable CA2201 // Do not raise reserved exception types throw new IndexOutOfRangeException(); +#pragma warning restore CA2201 // Do not raise reserved exception types #pragma warning restore S112 } diff --git a/test/MockHttp.Server.Tests/Fixtures/MockHttpServerFixture.cs b/test/MockHttp.Server.Tests/Fixtures/MockHttpServerFixture.cs index 00de305e..0618d33e 100644 --- a/test/MockHttp.Server.Tests/Fixtures/MockHttpServerFixture.cs +++ b/test/MockHttp.Server.Tests/Fixtures/MockHttpServerFixture.cs @@ -29,7 +29,15 @@ protected MockHttpServerFixture(string scheme) .CreateLogger(); LoggerFactory = new SerilogLoggerFactory(logger); Handler = new MockHttpHandler(); - Server = new MockHttpServer(Handler, LoggerFactory, SupportsIpv6() ? $"{scheme}://[::1]:0" : $"{scheme}://127.0.0.1:0"); + Server = new MockHttpServer( + Handler, + LoggerFactory, + new Uri( + SupportsIpv6() + ? $"{scheme}://[::1]:0" + : $"{scheme}://127.0.0.1:0" + ) + ); Server .Configure(builder => builder .Use((_, next) => diff --git a/test/MockHttp.Server.Tests/MockHttpServerTests.cs b/test/MockHttp.Server.Tests/MockHttpServerTests.cs index 366992af..67047441 100644 --- a/test/MockHttp.Server.Tests/MockHttpServerTests.cs +++ b/test/MockHttp.Server.Tests/MockHttpServerTests.cs @@ -11,6 +11,8 @@ namespace MockHttp; [Collection(nameof(DisableParallelization))] public sealed class MockHttpServerTests : IClassFixture, IDisposable { + private static readonly Uri BaseUri = new("http://127.0.0.1:0"); + private readonly MockHttpServerFixture _fixture; private readonly ITestOutputHelper _testOutputHelper; @@ -247,7 +249,7 @@ public void When_creating_server_with_null_handler_it_should_throw() // Act #pragma warning disable CS8604 - Func act = () => new MockHttpServer(mockHttpHandler, ""); + Func act = () => new MockHttpServer(mockHttpHandler, BaseUri); #pragma warning restore CS8604 // Assert @@ -261,7 +263,7 @@ public async Task When_creating_and_starting_server_with_null_logger_it_should_n // Act // ReSharper disable once ExpressionIsAlwaysNull - Func act = () => new MockHttpServer(new MockHttpHandler(), loggerFactory, "http://127.0.0.1:0"); + Func act = () => new MockHttpServer(new MockHttpHandler(), loggerFactory, BaseUri); // Assert using MockHttpServer server = act.Should().NotThrow().Which; @@ -270,6 +272,7 @@ public async Task When_creating_and_starting_server_with_null_logger_it_should_n } [Fact] + [Obsolete("Removed in next major version.")] public void When_creating_server_with_null_host_it_should_throw() { string? hostUrl = null; @@ -284,6 +287,7 @@ public void When_creating_server_with_null_host_it_should_throw() } [Fact] + [Obsolete("Removed in next major version.")] public void When_creating_server_with_invalid_host_it_should_throw() { const string hostUrl = "relative/uri/is/invalid"; @@ -297,9 +301,10 @@ public void When_creating_server_with_invalid_host_it_should_throw() } [Fact] - public void When_creating_server_with_absolute_uri_it_should_not_throw_and_take_host_from_uri() + [Obsolete("Removed in next major version.")] + public void When_creating_server_with_absolute_uri_it_should_not_throw_and_take_host_from_url() { - const string hostUrl = "https://relative:789/uri/is/invalid"; + var hostUrl = new Uri("https://relative:789/uri/is/invalid"); const string expectedHostUrl = "https://relative:789"; // Act @@ -310,10 +315,24 @@ public void When_creating_server_with_absolute_uri_it_should_not_throw_and_take_ act.Should().NotThrow().Which.HostUrl.Should().Be(expectedHostUrl); } + [Fact] + public void When_creating_server_with_absolute_uri_it_should_not_throw_and_take_host_from_uri() + { + var hostUrl = new Uri("https://relative:789/uri/is/invalid"); + var expectedHostUrl = new Uri("https://relative:789"); + + // Act + // ReSharper disable once ExpressionIsAlwaysNull + Func act = () => new MockHttpServer(new MockHttpHandler(), hostUrl); + + // Assert + act.Should().NotThrow().Which.HostUri.Should().Be(expectedHostUrl); + } + [Fact] public async Task Given_server_is_started_when_starting_again_it_should_throw() { - using var server = new MockHttpServer(_fixture.Handler, "http://127.0.0.1:0"); + using var server = new MockHttpServer(_fixture.Handler, BaseUri); await server.StartAsync(); server.IsStarted.Should().BeTrue(); @@ -327,7 +346,7 @@ public async Task Given_server_is_started_when_starting_again_it_should_throw() [Fact] public async Task Given_server_is_not_started_when_stopped_it_should_throw() { - using var server = new MockHttpServer(_fixture.Handler, "http://127.0.0.1:0"); + using var server = new MockHttpServer(_fixture.Handler, BaseUri); server.IsStarted.Should().BeFalse(); // Act @@ -343,7 +362,7 @@ public void When_creating_server_handler_it_should_set_property() var handler = new MockHttpHandler(); // Act - var server = new MockHttpServer(handler, "http://127.0.0.1:0"); + var server = new MockHttpServer(handler, BaseUri); // Assert server.Handler.Should().Be(handler); diff --git a/test/MockHttp.Testing/DelegateTestCase.cs b/test/MockHttp.Testing/DelegateTestCase.cs index adb8dc9b..80f09d15 100644 --- a/test/MockHttp.Testing/DelegateTestCase.cs +++ b/test/MockHttp.Testing/DelegateTestCase.cs @@ -9,7 +9,12 @@ public class DelegateTestCase : List private DelegateTestCase(Delegate @delegate) { - Name = @delegate.GetMethodInfo().Name; + if (@delegate is null) + { + throw new ArgumentNullException(nameof(@delegate)); + } + + Name = @delegate.GetMethodInfo()!.Name; Delegate = @delegate; Add(Name); Add(@delegate); @@ -18,7 +23,7 @@ private DelegateTestCase(Delegate @delegate) public IEnumerable GetNullArgumentTestCases(bool withoutName = false) { const int paramOffset = 2; - MethodInfo methodInfo = Delegate.GetMethodInfo(); + MethodInfo methodInfo = Delegate.GetMethodInfo()!; ParameterInfo[] parameters = methodInfo.GetParameters(); for (int i = paramOffset; i < Count; i++) { diff --git a/test/MockHttp.Testing/NullArgumentTest.cs b/test/MockHttp.Testing/NullArgumentTest.cs index 24778256..7f362a9f 100644 --- a/test/MockHttp.Testing/NullArgumentTest.cs +++ b/test/MockHttp.Testing/NullArgumentTest.cs @@ -16,7 +16,7 @@ public static void Execute(params object[] testArgs) string testCase = (string)testArgs[0]; var func = (Delegate)testArgs[1]; string expectedParamName = (string)testArgs[2]; - ParameterInfo param = func.GetMethodInfo().GetParameters().Single(p => p.Name == expectedParamName); + ParameterInfo param = func.GetMethodInfo()!.GetParameters().Single(p => p.Name == expectedParamName); object[] args = testArgs.Skip(3).ToArray(); if (args.Length == 0) {