🎉 mocks and moq

master
Marc CHEVALDONNE 1 year ago
parent 495db318ba
commit 680451fd01

@ -0,0 +1,48 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mocks", "mocks", "{98474E06-6ECA-468B-9693-30AA3708FA0A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "mocks\Model\Model.csproj", "{12FE8D34-611E-4AB9-93BE-C74A7D947405}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UTests", "mocks\UTests\UTests.csproj", "{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UTests2", "mocks\UTests2\UTests2.csproj", "{991E0C4E-48DE-4699-BCF7-070029923143}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UTests3", "mocks\UTests3\UTests3.csproj", "{A9FE0291-58A1-42E5-9768-34B3A33F4116}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{12FE8D34-611E-4AB9-93BE-C74A7D947405}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{12FE8D34-611E-4AB9-93BE-C74A7D947405}.Debug|Any CPU.Build.0 = Debug|Any CPU
{12FE8D34-611E-4AB9-93BE-C74A7D947405}.Release|Any CPU.ActiveCfg = Release|Any CPU
{12FE8D34-611E-4AB9-93BE-C74A7D947405}.Release|Any CPU.Build.0 = Release|Any CPU
{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4}.Release|Any CPU.Build.0 = Release|Any CPU
{991E0C4E-48DE-4699-BCF7-070029923143}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{991E0C4E-48DE-4699-BCF7-070029923143}.Debug|Any CPU.Build.0 = Debug|Any CPU
{991E0C4E-48DE-4699-BCF7-070029923143}.Release|Any CPU.ActiveCfg = Release|Any CPU
{991E0C4E-48DE-4699-BCF7-070029923143}.Release|Any CPU.Build.0 = Release|Any CPU
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9FE0291-58A1-42E5-9768-34B3A33F4116}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{12FE8D34-611E-4AB9-93BE-C74A7D947405} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{93AA2CF9-A29A-41D2-9ECC-87BE7BD121A4} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{991E0C4E-48DE-4699-BCF7-070029923143} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
{A9FE0291-58A1-42E5-9768-34B3A33F4116} = {98474E06-6ECA-468B-9693-30AA3708FA0A}
EndGlobalSection
EndGlobal

@ -0,0 +1,6 @@
namespace Model;
public interface IEmailService
{
Task AskConfirmation(Nounours nounours);
}

@ -0,0 +1,8 @@
namespace Model;
public interface INounoursStore
{
Task<Nounours?> Add(Nounours nounours);
Task<bool> Remove(Nounours nounours);
}

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,11 @@
namespace Model;
public class Nounours
{
public string Email { get; private set; }
public Nounours(string email)
{
Email = email;
}
}

@ -0,0 +1,34 @@
namespace Model;
public class NounoursManager
{
private INounoursStore nounoursStore;
private IEmailService emailService;
public NounoursManager(INounoursStore nounoursStore, IEmailService emailService)
{
this.nounoursStore = nounoursStore;
this.emailService = emailService;
}
public async Task<bool> AddNewNounours(Nounours nounours)
{
var result = await nounoursStore.Add(nounours);
if(result == null) return false;
try
{
await emailService.AskConfirmation(nounours);
}
catch
{
bool removed = await nounoursStore.Remove(nounours);
if(!removed) throw new Exception("this should not happen...");
return false;
}
return true;
}
}

@ -0,0 +1,27 @@
using System.ComponentModel;
using Model;
public class MockEmailService : IEmailService
{
public MockEmailService(bool sendEmail)
{
SendEmail = sendEmail;
}
public string? EmailSentTo {get; private set; }
private bool SendEmail {get; set;}
public Task AskConfirmation(Nounours nounours)
{
if(SendEmail)
{
EmailSentTo = nounours.Email;
return Task.CompletedTask;
}
else
{
throw new Exception();
}
}
}

@ -0,0 +1,43 @@
using Model;
namespace UTests;
public class MockNounoursStore : INounoursStore
{
public MockNounoursStore(bool canAdd, bool canRemove)
{
CanAdd = canAdd;
CanRemove = canRemove;
}
private bool CanAdd {get; set; }
private bool CanRemove {get; set; }
public Nounours? AddedNounours { get; private set; }
public Task<Nounours?> Add(Nounours nounours)
{
if(CanAdd)
{
AddedNounours = nounours;
return Task.FromResult<Nounours?>(nounours);
}
else
{
return Task.FromResult<Nounours?>(null);
}
}
public Task<bool> Remove(Nounours nounours)
{
if(CanRemove)
{
AddedNounours = null;
return Task.FromResult(true);
}
else
{
return Task.FromResult(false);
}
}
}

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,81 @@
using Model;
namespace UTests;
public class UnitTests
{
[Fact]
public async Task Test_AddNewNounours_Success()
{
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore(canAdd: true, canRemove: true);
MockEmailService emailService = new MockEmailService(sendEmail: true);
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
var nounours = new Nounours("chucky.chucky@hell.com");
//execute the method to test
await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.Equal(nounours.Email, nounoursStore.AddedNounours?.Email);
Assert.Equal(nounours.Email, emailService.EmailSentTo);
}
[Fact]
public async Task Test_AddNewNounours_Fail_AlreadyExists()
{
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore(canAdd: false, canRemove: true);
MockEmailService emailService = new MockEmailService(sendEmail: true);
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
var nounours = new Nounours("chucky.chucky@hell.com");
//execute the method to test
await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.Null(nounoursStore.AddedNounours);
Assert.Null(emailService.EmailSentTo);
}
[Fact]
public async Task Test_AddNewNounours_Fail_BadEmail()
{
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore(canAdd: true, canRemove: true);
MockEmailService emailService = new MockEmailService(sendEmail: false);
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
var nounours = new Nounours("chucky.chucky@hell.com");
//execute the method to test
await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.Null(nounoursStore.AddedNounours);
Assert.Null(emailService.EmailSentTo);
}
[Fact]
public async Task Test_AddNewNounours_Fail_ExceptionWhenRemoving()
{
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore(canAdd: true, canRemove: false);
MockEmailService emailService = new MockEmailService(sendEmail: false);
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
var nounours = new Nounours("chucky.chucky@hell.com");
//assert it throws an exception
_ = await Assert.ThrowsAsync<Exception>(async () => await mgr.AddNewNounours(nounours));
//assert the interactions went correctly
Assert.Equal(nounours.Email, nounoursStore.AddedNounours?.Email);
}
}

@ -0,0 +1,23 @@
using Model;
namespace UTests2;
public class MockEmailService : IEmailService
{
public Func<Nounours, bool> AskConfirmation {get; set;} = null!;
Task IEmailService.AskConfirmation(Nounours nounours)
{
if(AskConfirmation != null)
{
if(AskConfirmation(nounours))
{
return Task.CompletedTask;
}
else
{
throw new Exception();
}
}
throw new Exception();
}
}

@ -0,0 +1,26 @@
using Model;
namespace UTests2;
public class MockNounoursStore : INounoursStore
{
public Func<Nounours?, Nounours?> Add {get; set;} = null!;
public Func<Nounours?, bool> Remove {get; set;} = null!;
Task<Nounours?> INounoursStore.Add(Nounours nounours)
{
if (Add != null)
{
return Task.FromResult(Add(nounours));
}
return Task.FromResult<Nounours?>(null);
}
Task<bool> INounoursStore.Remove(Nounours nounours)
{
if(Remove != null)
{
return Task.FromResult(Remove(nounours));
}
return Task.FromResult(false);
}
}

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,152 @@
using Model;
namespace UTests2;
public class UnitTests
{
[Fact]
public async Task Test_AddNewNounours_Success()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore
{
Add = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return n;
}
};
MockEmailService emailService = new MockEmailService
{
AskConfirmation = n =>
{
Assert.Equal("chucky.chucky@hell.com", n.Email);
return true;
}
};
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
//execute the method to test
bool result = await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.True(result);
}
[Fact]
public async Task Test_AddNewNounours_Fail_AlreadyExists()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore
{
Add = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return null;
},
Remove = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return true;
}
};
MockEmailService emailService = new MockEmailService
{
AskConfirmation = n =>
{
Assert.Equal("chucky.chucky@hell.com", n.Email);
return true;
}
};
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
//execute the method to test
bool result = await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.False(result);
}
[Fact]
public async Task Test_AddNewNounours_Fail_BadEmail()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore
{
Add = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return n;
},
Remove = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return true;
}
};
MockEmailService emailService = new MockEmailService
{
AskConfirmation = n =>
{
Assert.Equal(nounours.Email, n.Email);
return false;
}
};
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
//execute the method to test
bool result = await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.False(result);
}
[Fact]
public async Task Test_AddNewNounours_Fail_ExceptionWhenRemoving()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
MockNounoursStore nounoursStore = new MockNounoursStore
{
Add = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return n;
},
Remove = n =>
{
Assert.Equal(nounours.Email, n?.Email);
return false;
}
};
MockEmailService emailService = new MockEmailService
{
AskConfirmation = n =>
{
Assert.Equal("chucky.chucky@hell.com", n.Email);
return false;
}
};
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(nounoursStore, emailService);
//assert it throws an exception
_ = await Assert.ThrowsAsync<Exception>(async () => await mgr.AddNewNounours(nounours));
}
}

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Model\Model.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,107 @@
using Model;
using Moq;
namespace UTests3;
public class UnitTests
{
[Fact]
public async Task Test_AddNewNounours_Success()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
var mockStore = new Mock<INounoursStore>();
mockStore.Setup(store => store.Add(nounours)).ReturnsAsync(() => nounours);
var mockEmailService = new Mock<IEmailService>();
//mockEmailService.Setup(service => service.AskConfirmation(nounours));
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(mockStore.Object, mockEmailService.Object);
//execute the method to test
bool result = await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.True(result);
mockStore.Verify(store => store.Add(nounours), Times.Once);
mockStore.Verify(store => store.Remove(nounours), Times.Never);
mockEmailService.Verify(store => store.AskConfirmation(nounours), Times.Once);
}
[Fact]
public async Task Test_AddNewNounours_Fail_AlreadyExists()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
var mockStore = new Mock<INounoursStore>();
mockStore.Setup(store => store.Add(nounours)).ReturnsAsync(() => null);
//mockStore.Setup(store => store.Remove(nounours)).ReturnsAsync(true);
var mockEmailService = new Mock<IEmailService>();
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(mockStore.Object, mockEmailService.Object);
//execute the method to test
bool result = await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.False(result);
mockStore.Verify(store => store.Add(nounours), Times.Once);
mockStore.VerifyNoOtherCalls();
mockEmailService.VerifyNoOtherCalls();
}
[Fact]
public async Task Test_AddNewNounours_Fail_BadEmail()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
var mockStore = new Mock<INounoursStore>();
mockStore.Setup(store => store.Add(nounours)).ReturnsAsync(() => nounours);
mockStore.Setup(store => store.Remove(nounours)).ReturnsAsync(true);
var mockEmailService = new Mock<IEmailService>();
mockEmailService.Setup(service => service.AskConfirmation(nounours)).Throws<Exception>();
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(mockStore.Object, mockEmailService.Object);
//execute the method to test
bool result = await mgr.AddNewNounours(nounours);
//assert the interactions went correctly
Assert.False(result);
mockStore.Verify(store => store.Add(nounours), Times.Once);
mockStore.Verify(store => store.Remove(nounours), Times.Once);
mockStore.VerifyNoOtherCalls();
mockEmailService.Verify(service => service.AskConfirmation(nounours), Times.Once);
mockEmailService.VerifyNoOtherCalls();
}
[Fact]
public async Task Test_AddNewNounours_Fail_ExceptionWhenRemoving()
{
var nounours = new Nounours("chucky.chucky@hell.com");
//setup the mocks
var mockStore = new Mock<INounoursStore>();
mockStore.Setup(store => store.Add(nounours)).ReturnsAsync(() => nounours);
mockStore.Setup(store => store.Remove(nounours)).ReturnsAsync(false);
var mockEmailService = new Mock<IEmailService>();
mockEmailService.Setup(service => service.AskConfirmation(nounours)).Throws<Exception>();
//setup the subject-under-test
NounoursManager mgr = new NounoursManager(mockStore.Object, mockEmailService.Object);
//assert it throws an exception
_ = await Assert.ThrowsAsync<Exception>(async () => await mgr.AddNewNounours(nounours));
mockStore.Verify(store => store.Add(nounours), Times.Once);
mockStore.Verify(store => store.Remove(nounours), Times.Once);
mockStore.VerifyNoOtherCalls();
mockEmailService.Verify(service => service.AskConfirmation(nounours), Times.Once);
mockEmailService.VerifyNoOtherCalls();
}
}
Loading…
Cancel
Save