Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: replace Moq with NSubstitute #85

Merged
merged 1 commit into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions test/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@

<ItemGroup>
<Using Include="FluentAssertions" />
<Using Include="Moq" />
<Using Include="NSubstitute" />
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="xunit" Version="2.6.1" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void Given_that_adapter_is_not_registered_when_getting_adapter_it_should_
public void Given_that_adapter_is_registered_when_getting_adapter_it_should_return_same_instance()
{
using var msg = new HttpRequestMessage();
IJsonAdapter adapter = Mock.Of<IJsonAdapter>();
IJsonAdapter adapter = Substitute.For<IJsonAdapter>();
var items = new Dictionary<Type, object> { { typeof(IJsonAdapter), adapter } };
var sut = new MockHttpRequestContext(msg, items);
sut.Services.Should().NotBeEmpty();
Expand Down
78 changes: 31 additions & 47 deletions test/MockHttp.Json.Tests/JsonContentMatcherTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@ namespace MockHttp.Json;

public sealed class JsonContentMatcherTests : IDisposable
{
private readonly Mock<IJsonAdapter> _adapterMock;
private readonly Mock<IEqualityComparer<string>> _equalityComparerMock;
private readonly Dictionary<Type, object> _services;
private readonly IJsonAdapter _adapterMock;
private readonly IEqualityComparer<string> _equalityComparerMock;
private readonly Dictionary<Type, object> _services = new();
private readonly HttpRequestMessage _requestMessage;
private readonly MockHttpRequestContext _requestContext;

public JsonContentMatcherTests()
{
_adapterMock = new Mock<IJsonAdapter>();
_adapterMock = Substitute.For<IJsonAdapter>();

_equalityComparerMock = new Mock<IEqualityComparer<string>>();
_equalityComparerMock = Substitute.For<IEqualityComparer<string>>();
_equalityComparerMock
.Setup(m => m.Equals(It.IsAny<string?>()!, It.IsAny<string?>()!))
.Equals(Arg.Any<string?>(), Arg.Any<string?>())
.Returns(true);

_services = new Dictionary<Type, object>();
_requestMessage = new HttpRequestMessage();
_requestContext = new MockHttpRequestContext(_requestMessage, _services);
}
Expand All @@ -30,25 +29,21 @@ public async Task Given_that_adapter_is_provided_to_ctor_when_matching_it_should
var jsonContentAsObject = new { PropertyName = "value" };
const string serializedJson = "{\"modifiedPropertyName\":\"modifiedValue\"}";
_adapterMock
.Setup(m => m.Serialize(jsonContentAsObject))
.Returns(serializedJson)
.Verifiable();
.Serialize(Arg.Any<object?>())
.Returns(serializedJson);

var globalAdapterMock = new Mock<IJsonAdapter>();
_services.Add(typeof(IJsonAdapter), globalAdapterMock.Object);
IJsonAdapter globalAdapterMock = Substitute.For<IJsonAdapter>();
_services.Add(typeof(IJsonAdapter), globalAdapterMock);

var sut = new JsonContentMatcher(jsonContentAsObject, _adapterMock.Object, _equalityComparerMock.Object);
var sut = new JsonContentMatcher(jsonContentAsObject, _adapterMock, _equalityComparerMock);

// Act
await sut.IsMatchAsync(_requestContext);

// Assert
_adapterMock.Verify();
globalAdapterMock.Verify(m => m.Serialize(It.IsAny<object?>()), Times.Never);
_equalityComparerMock
.Verify(m => m.Equals(It.IsAny<string>(), serializedJson),
Times.Once
);
_adapterMock.Received(1).Serialize(jsonContentAsObject);
globalAdapterMock.DidNotReceiveWithAnyArgs().Serialize(Arg.Any<object?>());
_ = _equalityComparerMock.Received(1).Equals(Arg.Any<string?>(), serializedJson);
}

[Fact]
Expand All @@ -57,74 +52,66 @@ public async Task Given_that_adapter_is_not_provided_to_ctor_when_matching_it_sh
var jsonContentAsObject = new { PropertyName = "value" };
const string serializedJson = "{\"modifiedPropertyName\":\"modifiedValue\"}";

var globalAdapterMock = new Mock<IJsonAdapter>();
IJsonAdapter globalAdapterMock = Substitute.For<IJsonAdapter>();
globalAdapterMock
.Setup(m => m.Serialize(jsonContentAsObject))
.Returns(serializedJson)
.Verifiable();
.Serialize(Arg.Any<object?>())
.Returns(serializedJson);

var sut = new JsonContentMatcher(jsonContentAsObject, null, _equalityComparerMock.Object);
var sut = new JsonContentMatcher(jsonContentAsObject, null, _equalityComparerMock);

// Act
_services.Add(typeof(IJsonAdapter), globalAdapterMock.Object);
_services.Add(typeof(IJsonAdapter), globalAdapterMock);
await sut.IsMatchAsync(_requestContext);

// Assert
globalAdapterMock.Verify();
_equalityComparerMock
.Verify(m => m.Equals(It.IsAny<string>(), serializedJson),
Times.Once
);
globalAdapterMock.Received(1).Serialize(jsonContentAsObject);
_ = _equalityComparerMock.Received(1).Equals(Arg.Any<string?>(), serializedJson);
}

[Fact]
public async Task Given_that_adapter_is_not_provided_to_ctor_and_no_global_adapter_is_available_when_matching_it_should_use_the_default()
{
var jsonContentAsObject = new { PropertyName = "value" };
const string serializedJson = "{\"PropertyName\":\"value\"}";
var sut = new JsonContentMatcher(jsonContentAsObject, null, _equalityComparerMock.Object);
var sut = new JsonContentMatcher(jsonContentAsObject, null, _equalityComparerMock);

// Act
_services.Should().NotContainKey(typeof(IJsonAdapter));
await sut.IsMatchAsync(_requestContext);

// Assert
_equalityComparerMock
.Verify(m => m.Equals(It.IsAny<string>(), serializedJson),
Times.Once
);
_ = _equalityComparerMock.Received(1).Equals(Arg.Any<string?>(), serializedJson);
}

[Fact]
public async Task Given_that_adapter_is_not_provided_to_ctor_when_matching_it_should_use_the_adapter()
{
const string jsonContentAsObject = "text";
var sut = new JsonContentMatcher(jsonContentAsObject, _adapterMock.Object, _equalityComparerMock.Object);
var sut = new JsonContentMatcher(jsonContentAsObject, _adapterMock, _equalityComparerMock);

// Act
await sut.IsMatchAsync(_requestContext);

// Assert
_adapterMock.Verify(m => m.Serialize(jsonContentAsObject), Times.Once);
_adapterMock.Received(1).Serialize(jsonContentAsObject);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task When_matching_it_should_return_the_results_of_the_comparer(bool equals)
{
var sut = new JsonContentMatcher("something to compare with", _adapterMock.Object, _equalityComparerMock.Object);
var sut = new JsonContentMatcher("something to compare with", _adapterMock, _equalityComparerMock);

_equalityComparerMock
.Setup(m => m.Equals(It.IsAny<string?>()!, It.IsAny<string?>()!))
.Returns(equals)
.Verifiable();
.Equals(Arg.Any<string?>(), Arg.Any<string?>())
.Returns(equals);

// Act
bool actual = await sut.IsMatchAsync(_requestContext);

// Assert
_equalityComparerMock.Verify();
_ =_equalityComparerMock.Received(1).Equals(Arg.Any<string?>(), Arg.Any<string?>());
actual.Should().Be(equals);
}

Expand All @@ -137,17 +124,14 @@ HttpContent content
{
using (content)
{
var sut = new JsonContentMatcher("something to compare with", _adapterMock.Object, _equalityComparerMock.Object);
var sut = new JsonContentMatcher("something to compare with", _adapterMock, _equalityComparerMock);
_requestMessage.Content = content;

// Act
await sut.IsMatchAsync(_requestContext);

// Assert
_equalityComparerMock
.Verify(m => m.Equals(string.Empty, It.IsAny<string>()),
Times.Once
);
_ = _equalityComparerMock.Received(1).Equals(string.Empty, Arg.Any<string?>());
}
}

Expand Down
13 changes: 4 additions & 9 deletions test/MockHttp.Json.Tests/MockConfigurationExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

public class MockConfigurationExtensionsTests
{
private readonly MockHttpHandler _sut;

public MockConfigurationExtensionsTests()
{
_sut = new MockHttpHandler();
}
private readonly MockHttpHandler _sut = new();

[Theory]
[MemberData(nameof(UseJsonAdapterNullTestCases))]
Expand All @@ -29,8 +24,8 @@ public void Given_that_arg_is_null_when_creating_instance_using_it_should_throw

public static IEnumerable<object?[]> UseJsonAdapterNullTestCases()
{
IMockConfiguration mockConfig = Mock.Of<IMockConfiguration>();
IJsonAdapter jsonAdapter = Mock.Of<IJsonAdapter>();
IMockConfiguration mockConfig = Substitute.For<IMockConfiguration>();
IJsonAdapter jsonAdapter = Substitute.For<IJsonAdapter>();

yield return new object?[] { null, jsonAdapter, nameof(mockConfig) };
yield return new object?[] { mockConfig, null, nameof(jsonAdapter) };
Expand All @@ -39,7 +34,7 @@ public void Given_that_arg_is_null_when_creating_instance_using_it_should_throw
[Fact]
public void When_using_it_should_register_adapter()
{
IJsonAdapter adapter = Mock.Of<IJsonAdapter>();
IJsonAdapter adapter = Substitute.For<IJsonAdapter>();

// Act
_sut.UseJsonAdapter(adapter);
Expand Down
17 changes: 8 additions & 9 deletions test/MockHttp.Tests/AnyRequestMatchingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@ public class AnyRequestMatchingTests

public AnyRequestMatchingTests()
{
static HttpRequestMatcher CreateMatcherMock(Func<bool> returns)
{
var matcherMock = new Mock<HttpRequestMatcher>();
matcherMock
.Setup(m => m.IsExclusive)
.Returns(returns);
return matcherMock.Object;
}

_sut = new AnyRequestMatching();

_matcher1 = CreateMatcherMock(() => _isExclusive1);
_matcher2 = CreateMatcherMock(() => _isExclusive2);
return;

static HttpRequestMatcher CreateMatcherMock(Func<bool> returns)
{
HttpRequestMatcher matcherMock = Substitute.For<HttpRequestMatcher>();
matcherMock.IsExclusive.Returns(_ => returns());
return matcherMock;
}
}

[Fact]
Expand Down
14 changes: 6 additions & 8 deletions test/MockHttp.Tests/Extensions/IRespondsExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ public class WithStream : IRespondsExtensionsTests
[InlineData(false)]
public async Task When_responding_with_stream_it_should_return_response(bool isSeekable)
{
using var ms = new CanSeekMemoryStream(Encoding.UTF8.GetBytes("content"), isSeekable);
using var ms = new CanSeekMemoryStream("content"u8.ToArray(), isSeekable);
var request = new HttpRequestMessage();
var expectedContent = new ByteArrayContent(Encoding.UTF8.GetBytes("content"));
var expectedContent = new ByteArrayContent("content"u8.ToArray());

// Act
// ReSharper disable once AccessToDisposedClosure
_sut.Respond(with => with.Body(ms));
HttpResponseMessage actualResponse = await _httpCall.SendAsync(new MockHttpRequestContext(request), CancellationToken.None);

Expand Down Expand Up @@ -90,9 +91,8 @@ public void When_responding_with_null_stream_it_should_throw()
[Fact]
public void When_responding_with_not_readable_stream_it_should_throw()
{
var streamMock = new Mock<Stream>();
streamMock.Setup(m => m.CanRead).Returns(false);
Stream? streamContent = streamMock.Object;
Stream streamContent = Substitute.For<Stream>();
streamContent.CanRead.Returns(false);

// Act
Action act = () => _sut.Respond(with => with.Body(streamContent));
Expand Down Expand Up @@ -199,10 +199,8 @@ public void Given_null_argument_when_executing_method_it_should_throw(params obj

public static IEnumerable<object?[]> TestCases()
{
var streamMock = new Mock<Stream> { CallBase = true };
streamMock.SetReturnsDefault(true);
using var content = new StringContent("");
IResponds<IResponseResult> responds = Mock.Of<IResponds<IResponseResult>>();
IResponds<IResponseResult> responds = Substitute.For<IResponds<IResponseResult>>();

DelegateTestCase[] testCases =
{
Expand Down
4 changes: 2 additions & 2 deletions test/MockHttp.Tests/Extensions/ListExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ public void Given_that_list_contains_instances_of_type_when_getting_index_it_sho
{
var list = new List<IFoo?>
{
Mock.Of<IFoo>(),
Substitute.For<IFoo>(),
null,
new Foo(),
new Foo(),
Mock.Of<IFoo>(),
Substitute.For<IFoo>(),
new FooBar(),
new Foo(),
new FooBar()
Expand Down
21 changes: 12 additions & 9 deletions test/MockHttp.Tests/Extensions/RequestMatchingExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public async Task When_configuring_formData_should_match(string urlEncodedFormDa
var request = new HttpRequestMessage
{
RequestUri = new Uri("http://127.0.0.1"),
Content = new ByteArrayContent(Encoding.UTF8.GetBytes("key1=value1&key2=value2"))
Content = new ByteArrayContent("key1=value1&key2=value2"u8.ToArray())
{
Headers =
{
Expand All @@ -319,8 +319,8 @@ public async Task When_configuring_formData_should_match_multipart(string urlEnc
{
var content = new MultipartFormDataContent
{
{ new ByteArrayContent(Encoding.UTF8.GetBytes("value1")), "key1" },
{ new ByteArrayContent(Encoding.UTF8.GetBytes("éôxÄ")), "key2" },
{ new ByteArrayContent("value1"u8.ToArray()), "key1" },
{ new ByteArrayContent("éôxÄ"u8.ToArray()), "key2" },
{ new StringContent("file content 1", Encoding.UTF8, MediaTypes.PlainText), "file1", "file1.txt" }
};
var request = new HttpRequestMessage
Expand Down Expand Up @@ -679,8 +679,11 @@ public void Given_null_argument_when_executing_method_it_should_throw(params obj

public static IEnumerable<object?[]> TestCases()
{
var streamMock = new Mock<Stream> { CallBase = true };
streamMock.SetReturnsDefault(true);
Stream streamMock = Substitute.For<Stream>();
streamMock.CanRead.Returns(true);
streamMock.CanWrite.Returns(true);
streamMock.CanSeek.Returns(true);
streamMock.CanTimeout.Returns(true);
var uri = new Uri("http://0.0.0.0");
var instance = new RequestMatching();

Expand Down Expand Up @@ -830,11 +833,11 @@ public void Given_null_argument_when_executing_method_it_should_throw(params obj
DelegateTestCase.Create(
RequestMatchingExtensions.Body,
instance,
Encoding.UTF8.GetBytes("content")),
"content"u8.ToArray()),
DelegateTestCase.Create(
RequestMatchingExtensions.Body,
instance,
streamMock.Object),
streamMock),
DelegateTestCase.Create(
RequestMatchingExtensions.WithoutBody,
instance),
Expand All @@ -850,11 +853,11 @@ public void Given_null_argument_when_executing_method_it_should_throw(params obj
DelegateTestCase.Create(
RequestMatchingExtensions.PartialBody,
instance,
Encoding.UTF8.GetBytes("partial content")),
"partial content"u8.ToArray()),
DelegateTestCase.Create(
RequestMatchingExtensions.PartialBody,
instance,
streamMock.Object),
streamMock),
DelegateTestCase.Create<RequestMatching, Action<RequestMatching>, RequestMatching>(
RequestMatchingExtensions.Any,
instance,
Expand Down
Loading
Loading