Skip to content

Commit f53e0a0

Browse files
committed
test: replace Moq with NSubstitute [skip ci]
1 parent 5713cf6 commit f53e0a0

20 files changed

+127
-97
lines changed

.editorconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -3333,7 +3333,7 @@ resharper_xaml_xaml_xamarin_forms_data_type_and_binding_context_type_mismatched_
33333333
resharper_xaml_x_key_attribute_disallowed_highlighting = error
33343334
resharper_xunit_xunit_test_with_console_output_highlighting = warning
33353335

3336-
[*.{json, xml, config, md, csproj, yaml, yml, Build.props}]
3336+
[*.{json,xml,config,md,csproj,yaml,yml,Build.props}]
33373337
indent_size = 2
33383338
tab_width = 2
33393339
#space_before_self_closing = false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/UserDictionary/Words/=reporttypes/@EntryIndexedValue">True</s:Boolean>
3+
<s:Boolean x:Key="/Default/UserDictionary/Words/=targetdir/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Net.Http;
22
using Microsoft.Extensions.Logging.Abstractions;
33
using Microsoft.Extensions.Options;
4-
using Moq;
54
using ReportGenerator.BitbucketPipe.Options;
65
using ReportGenerator.BitbucketPipe.Tests.BDD;
76
using ReportGenerator.BitbucketPipe.Tests.Helpers;
@@ -11,7 +10,7 @@ namespace ReportGenerator.BitbucketPipe.Tests.BitbucketClientTests;
1110
public class BitbucketClientSpecificationBase : SpecificationBase
1211
{
1312
private BitbucketClientMock _bitbucketClientMock;
14-
protected Mock<HttpMessageHandler> HttpMessageHandlerMock => _bitbucketClientMock.HttpMessageHandlerMock;
13+
protected MockHttpMessageHandler HttpMessageHandlerMock => _bitbucketClientMock.HttpMessageHandlerMock;
1514
protected BitbucketClient BitbucketClient { get; private set; }
1615

1716
protected override void Given()
@@ -25,17 +24,16 @@ protected override void Given()
2524
var pipeOptions = new PipeOptions { CreateBuildStatus = true };
2625
var authOptions = new BitbucketAuthenticationOptions { Username = "user", AppPassword = "pass" };
2726

28-
_bitbucketClientMock =
29-
new BitbucketClientMock();
27+
_bitbucketClientMock = new BitbucketClientMock();
3028

3129
BitbucketClient = new BitbucketClient(
32-
new HttpClient(_bitbucketClientMock.HttpMessageHandlerMock.Object),
30+
new HttpClient(_bitbucketClientMock.HttpMessageHandlerMock),
3331
NullLogger<BitbucketClient>.Instance,
34-
Mock.Of<IOptions<PublishReportOptions>>(o => o.Value == new PublishReportOptions()),
35-
Mock.Of<IOptions<CoverageRequirementsOptions>>(o => o.Value == requirementsOptions),
36-
Mock.Of<IOptions<BitbucketOptions>>(o => o.Value == bitbucketOptions),
37-
Mock.Of<IOptions<PipeOptions>>(o => o.Value == pipeOptions),
38-
Mock.Of<IOptions<BitbucketAuthenticationOptions>>(o => o.Value == authOptions),
32+
new OptionsWrapper<PublishReportOptions>(new PublishReportOptions()),
33+
new OptionsWrapper<CoverageRequirementsOptions>(requirementsOptions),
34+
new OptionsWrapper<BitbucketOptions>(bitbucketOptions),
35+
new OptionsWrapper<PipeOptions>(pipeOptions),
36+
new OptionsWrapper<BitbucketAuthenticationOptions>(authOptions),
3937
TestEnvironment.EnvironmentInfo);
4038
}
4139
}

tests/ReportGenerator.BitbucketPipe.Tests/BitbucketClientTests/When_Making_A_Request_To_Create_Build_Status.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Net.Http;
33
using System.Threading.Tasks;
4-
using Moq;
54
using ReportGenerator.BitbucketPipe.Model;
65
using ReportGenerator.BitbucketPipe.Tests.BDD;
76
using ReportGenerator.BitbucketPipe.Tests.Helpers;
@@ -21,7 +20,7 @@ await BitbucketClient.CreateCommitBuildStatusAsync(new CoverageSummary
2120
[Then]
2221
public void It_Should_Make_One_Post_Call_To_Create_Build_Status()
2322
{
24-
HttpMessageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
23+
HttpMessageHandlerMock.VerifySendCall(1, request =>
2524
request.Method == HttpMethod.Post &&
2625
request.RequestUri.PathAndQuery.EndsWith("workspace/repo-slug/commit/222be690/statuses/build",
2726
StringComparison.Ordinal));

tests/ReportGenerator.BitbucketPipe.Tests/BitbucketClientTests/When_Making_A_Request_To_Create_Report.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Net.Http;
33
using System.Threading.Tasks;
4-
using Moq;
4+
using NSubstitute.ReceivedExtensions;
55
using ReportGenerator.BitbucketPipe.Model;
66
using ReportGenerator.BitbucketPipe.Tests.BDD;
77
using ReportGenerator.BitbucketPipe.Tests.Helpers;
@@ -21,7 +21,7 @@ protected override async Task WhenAsync()
2121
[Then]
2222
public void It_Should_Make_One_Put_Call_To_Create_Report()
2323
{
24-
HttpMessageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
24+
HttpMessageHandlerMock.VerifySendCall(1, request =>
2525
request.Method == HttpMethod.Put &&
2626
request.RequestUri.PathAndQuery.EndsWith(
2727
"workspace/repo-slug/commit/222be690/reports/code-coverage", StringComparison.Ordinal));
@@ -30,7 +30,7 @@ public void It_Should_Make_One_Put_Call_To_Create_Report()
3030
[Then]
3131
public void It_Should_Serialize_Report_Using_Snake_Case()
3232
{
33-
HttpMessageHandlerMock.VerifySendAsyncCall(Times.AtLeastOnce(),
33+
HttpMessageHandlerMock.VerifySendCall(Quantity.AtLeastOne(),
3434
request => request.Content.ReadAsStringAsync().Result.Contains("\"report_type\":"));
3535
}
3636
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
using System.Net;
22
using System.Net.Http;
33
using System.Threading;
4-
using System.Threading.Tasks;
5-
using Moq;
6-
using Moq.Protected;
4+
using NSubstitute;
75

86
namespace ReportGenerator.BitbucketPipe.Tests.Helpers;
97

108
public class BitbucketClientMock
119
{
1210
public BitbucketClientMock()
1311
{
14-
HttpMessageHandlerMock = new Mock<HttpMessageHandler>();
15-
HttpMessageHandlerMock
16-
.Protected()
17-
.Setup<Task<HttpResponseMessage>>("SendAsync",
18-
ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
19-
.Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)));
12+
HttpMessageHandlerMock = Substitute.ForPartsOf<MockHttpMessageHandler>();
13+
HttpMessageHandlerMock.MockSend(Arg.Any<HttpRequestMessage>(), Arg.Any<CancellationToken>())
14+
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
2015
}
2116

22-
public Mock<HttpMessageHandler> HttpMessageHandlerMock { get; }
17+
public MockHttpMessageHandler HttpMessageHandlerMock { get; }
2318
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Net.Http;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace ReportGenerator.BitbucketPipe.Tests.Helpers;
6+
7+
public abstract class MockHttpMessageHandler : HttpMessageHandler
8+
{
9+
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
10+
CancellationToken cancellationToken) => Task.FromResult(MockSend(request, cancellationToken));
11+
12+
protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) =>
13+
MockSend(request, cancellationToken);
14+
15+
public abstract HttpResponseMessage MockSend(HttpRequestMessage request, CancellationToken cancellationToken);
16+
}

tests/ReportGenerator.BitbucketPipe.Tests/Helpers/SendAsyncVerifier.cs

+11-8
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@
22
using System.Linq.Expressions;
33
using System.Net.Http;
44
using System.Threading;
5-
using System.Threading.Tasks;
6-
using Moq;
7-
using Moq.Protected;
5+
using NSubstitute;
6+
using NSubstitute.ReceivedExtensions;
87

98
namespace ReportGenerator.BitbucketPipe.Tests.Helpers;
109

1110
public static class SendAsyncVerifier
1211
{
13-
public static void VerifySendAsyncCall(this Mock<HttpMessageHandler> messageHandler, Times times,
14-
Expression<Func<HttpRequestMessage, bool>> requestMatch) =>
15-
messageHandler.Protected()
16-
.Verify<Task<HttpResponseMessage>>("SendAsync", times, ItExpr.Is(requestMatch),
17-
ItExpr.IsAny<CancellationToken>());
12+
public static void VerifySendCall(this MockHttpMessageHandler messageHandler, int requiresNumberOfCalls,
13+
Expression<Predicate<HttpRequestMessage>> requestMatch) => messageHandler.Received(requiresNumberOfCalls)
14+
.MockSend(Arg.Is(requestMatch), Arg.Any<CancellationToken>());
15+
16+
public static void VerifySendCall(this MockHttpMessageHandler messageHandler, Quantity requiresQuantityOfCalls,
17+
Expression<Predicate<HttpRequestMessage>> requestMatch)
18+
{
19+
messageHandler.Received(requiresQuantityOfCalls).MockSend(Arg.Is(requestMatch), Arg.Any<CancellationToken>());
20+
}
1821
}

tests/ReportGenerator.BitbucketPipe.Tests/Helpers/TestEnvironment.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
using System.Collections.Generic;
2-
using Moq;
1+
using System;
2+
using System.Collections.Generic;
3+
using NSubstitute;
34
using ReportGenerator.BitbucketPipe.Utils;
45

56
namespace ReportGenerator.BitbucketPipe.Tests.Helpers;
67

8+
public abstract class DefaultEnvironmentVariableProvider : IEnvironmentVariableProvider
9+
{
10+
public virtual string GetEnvironmentVariable(string variableName) => throw new NotImplementedException();
11+
}
12+
713
public static class TestEnvironment
814
{
915
public static BitbucketEnvironmentInfo EnvironmentInfo { get; } = new()
@@ -22,10 +28,10 @@ public static IEnvironmentVariableProvider CreateMockEnvironment(
2228
environment.TryAdd(EnvironmentVariable.BitbucketRepoSlug, "repo-slug");
2329
}
2430

25-
var envVarMock = new Mock<IEnvironmentVariableProvider> { CallBase = true };
26-
envVarMock.Setup(provider => provider.GetEnvironmentVariable(It.IsAny<string>()))
27-
.Returns((string varName) => environment.GetValueOrDefault(varName));
31+
var envVarProvider = Substitute.ForPartsOf<DefaultEnvironmentVariableProvider>();
32+
envVarProvider.GetEnvironmentVariable(Arg.Any<string>())
33+
.Returns(x => environment.GetValueOrDefault(x.ArgAt<string>(0)));
2834

29-
return envVarMock.Object;
35+
return envVarProvider;
3036
}
3137
}

tests/ReportGenerator.BitbucketPipe.Tests/OptionsConfigurationTests/When_Configuring_BitbucketOptions.cs

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
using FluentAssertions;
2-
using Moq;
2+
using NSubstitute;
33
using ReportGenerator.BitbucketPipe.Options;
44
using ReportGenerator.BitbucketPipe.Tests.BDD;
5+
using ReportGenerator.BitbucketPipe.Tests.Helpers;
56
using ReportGenerator.BitbucketPipe.Utils;
67

78
namespace ReportGenerator.BitbucketPipe.Tests.OptionsConfigurationTests;
@@ -15,11 +16,17 @@ protected override void Given()
1516
{
1617
base.Given();
1718
_options = new BitbucketOptions();
18-
_environmentVariableProvider = Mock.Of<IEnvironmentVariableProvider>(provider =>
19-
provider.GetEnvironmentVariable(It.Is<string>(s => s == EnvironmentVariable.BuildStatusName)) ==
20-
"My Coverage Status" &&
21-
provider.GetEnvironmentVariable(It.Is<string>(s => s == EnvironmentVariable.PipelineReportTitle)) ==
22-
"My Coverage Report");
19+
_environmentVariableProvider = Substitute.ForPartsOf<DefaultEnvironmentVariableProvider>();
20+
21+
_environmentVariableProvider.GetEnvironmentVariable(Arg.Any<string>()).Returns(
22+
x =>
23+
{
24+
string varName = (string)x[0];
25+
26+
return varName == EnvironmentVariable.BuildStatusName ? "My Coverage Status" :
27+
varName == EnvironmentVariable.PipelineReportTitle ? "My Coverage Report" :
28+
"";
29+
});
2330
}
2431

2532
protected override void When()

tests/ReportGenerator.BitbucketPipe.Tests/PipeRunnerTests/TestPipeRunner.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected override IServiceCollection ConfigureServices()
2626
services.FirstOrDefault(service => service.ServiceType == typeof(BitbucketClient));
2727
services.Remove(bitbucketClientService);
2828
services.AddHttpClient<BitbucketClient>()
29-
.ConfigurePrimaryHttpMessageHandler(() => _bitbucketClientMock.HttpMessageHandlerMock.Object);
29+
.ConfigurePrimaryHttpMessageHandler(() => _bitbucketClientMock.HttpMessageHandlerMock);
3030

3131
// add mock IEnvironmentVariablesProvider
3232
var environmentVariableProviderService =

tests/ReportGenerator.BitbucketPipe.Tests/PipeRunnerTests/When_Running_Pipe_With_Coverage_Requirements_That_Are_Met.cs

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Net.Http;
5+
using System.Threading;
56
using System.Threading.Tasks;
67
using FluentAssertions;
7-
using Moq;
8+
using NSubstitute;
89
using ReportGenerator.BitbucketPipe.Options;
910
using ReportGenerator.BitbucketPipe.Tests.BDD;
1011
using ReportGenerator.BitbucketPipe.Tests.Helpers;
@@ -13,7 +14,7 @@ namespace ReportGenerator.BitbucketPipe.Tests.PipeRunnerTests;
1314

1415
public class When_Running_Pipe_With_Coverage_Requirements_That_Are_Met : SpecificationBase
1516
{
16-
private Mock<HttpMessageHandler> _messageHandlerMock;
17+
private MockHttpMessageHandler _messageHandlerMock;
1718
private TestPipeRunner _pipeRunner;
1819

1920
protected override void Given()
@@ -54,15 +55,16 @@ public void It_Should_Create_Report_In_Destination_Directory()
5455
[Then]
5556
public void It_Should_Create_Bitbucket_Report_With_Passed_Status()
5657
{
57-
_messageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
58-
request.RequestUri.PathAndQuery.EndsWith("reports/code-coverage", StringComparison.Ordinal) &&
59-
request.Content.ReadAsStringAsync().Result.Contains("\"result\":\"PASSED\""));
58+
_messageHandlerMock.Received(1).MockSend(Arg.Is<HttpRequestMessage>(request =>
59+
request.RequestUri.PathAndQuery.EndsWith("reports/code-coverage", StringComparison.Ordinal) &&
60+
request.Content.ReadAsStringAsync().Result.Contains("\"result\":\"PASSED\"")),
61+
Arg.Any<CancellationToken>());
6062
}
6163

6264
[Then]
6365
public void It_Should_Create_Build_Status_With_Successful_Status()
6466
{
65-
_messageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
67+
_messageHandlerMock.VerifySendCall(1, request =>
6668
request.RequestUri.PathAndQuery.EndsWith("statuses/build", StringComparison.Ordinal) &&
6769
request.Content.ReadAsStringAsync().Result.Contains("\"state\":\"SUCCESSFUL\""));
6870
}

tests/ReportGenerator.BitbucketPipe.Tests/PipeRunnerTests/When_Running_Pipe_With_Coverage_Requirements_That_Are_Not_Met.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4-
using System.Net.Http;
54
using System.Threading.Tasks;
65
using FluentAssertions;
7-
using Moq;
86
using ReportGenerator.BitbucketPipe.Options;
97
using ReportGenerator.BitbucketPipe.Tests.BDD;
108
using ReportGenerator.BitbucketPipe.Tests.Helpers;
@@ -13,7 +11,7 @@ namespace ReportGenerator.BitbucketPipe.Tests.PipeRunnerTests;
1311

1412
public class When_Running_Pipe_With_Coverage_Requirements_That_Are_Not_Met : SpecificationBase
1513
{
16-
private Mock<HttpMessageHandler> _messageHandlerMock;
14+
private MockHttpMessageHandler _messageHandlerMock;
1715
private TestPipeRunner _pipeRunner;
1816

1917
protected override void Given()
@@ -54,15 +52,15 @@ public void It_Should_Create_Report_In_Destination_Directory()
5452
[Then]
5553
public void It_Should_Create_Bitbucket_Report_With_Failed_Status()
5654
{
57-
_messageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
55+
_messageHandlerMock.VerifySendCall(1, request =>
5856
request.RequestUri.PathAndQuery.EndsWith("reports/code-coverage", StringComparison.Ordinal) &&
5957
request.Content.ReadAsStringAsync().Result.Contains("\"result\":\"FAILED\""));
6058
}
6159

6260
[Then]
6361
public void It_Should_Create_Build_Status_With_Failed_Status()
6462
{
65-
_messageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
63+
_messageHandlerMock.VerifySendCall(1, request =>
6664
request.RequestUri.PathAndQuery.EndsWith("statuses/build", StringComparison.Ordinal) &&
6765
request.Content.ReadAsStringAsync().Result.Contains("\"state\":\"FAILED\""));
6866
}

tests/ReportGenerator.BitbucketPipe.Tests/PipeRunnerTests/When_Running_Pipe_With_Create_Build_Status_Flag_Set_To_False.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4-
using System.Net.Http;
54
using System.Threading.Tasks;
65
using FluentAssertions;
7-
using Moq;
86
using ReportGenerator.BitbucketPipe.Options;
97
using ReportGenerator.BitbucketPipe.Tests.BDD;
108
using ReportGenerator.BitbucketPipe.Tests.Helpers;
@@ -13,7 +11,7 @@ namespace ReportGenerator.BitbucketPipe.Tests.PipeRunnerTests;
1311

1412
public class When_Running_Pipe_With_Create_Build_Status_Flag_Set_To_False : SpecificationBase
1513
{
16-
private Mock<HttpMessageHandler> _messageHandlerMock;
14+
private MockHttpMessageHandler _messageHandlerMock;
1715
private TestPipeRunner _pipeRunner;
1816

1917
protected override void Given()
@@ -51,14 +49,14 @@ public void It_Should_Create_Report_In_Destination_Directory()
5149
[Then]
5250
public void It_Should_Create_Bitbucket_Report()
5351
{
54-
_messageHandlerMock.VerifySendAsyncCall(Times.Once(), request =>
52+
_messageHandlerMock.VerifySendCall(1, request =>
5553
request.RequestUri.PathAndQuery.EndsWith("reports/code-coverage", StringComparison.Ordinal));
5654
}
5755

5856
[Then]
5957
public void It_Should_Not_Create_Build_Status_With_Successful_Status()
6058
{
61-
_messageHandlerMock.VerifySendAsyncCall(Times.Never(), request =>
59+
_messageHandlerMock.VerifySendCall(0, request =>
6260
request.RequestUri.PathAndQuery.EndsWith("statuses/build", StringComparison.Ordinal));
6361
}
6462
}

0 commit comments

Comments
 (0)