ToolBX.Eloquentest
2.1.2-beta4
See the version list below for details.
dotnet add package ToolBX.Eloquentest --version 2.1.2-beta4
NuGet\Install-Package ToolBX.Eloquentest -Version 2.1.2-beta4
<PackageReference Include="ToolBX.Eloquentest" Version="2.1.2-beta4" />
paket add ToolBX.Eloquentest --version 2.1.2-beta4
#r "nuget: ToolBX.Eloquentest, 2.1.2-beta4"
// Install ToolBX.Eloquentest as a Cake Addin #addin nuget:?package=ToolBX.Eloquentest&version=2.1.2-beta4&prerelease // Install ToolBX.Eloquentest as a Cake Tool #tool nuget:?package=ToolBX.Eloquentest&version=2.1.2-beta4&prerelease
Eloquentest
A simple to use .NET unit testing framework built on top of MSTest and Moq. It also includes built-in support for services that are injected using [AutoInject].
Getting started
Here is the dumbest service you can imagine.
public class DumbestServiceYouCanImagine
{
public string Format(int number)
{
return number == 0 ? "It's zero" : "It's not zero";
}
}
Here is the dumbest unit test for the dumbest service you can imagine.
[TestClass]
public class DumbestServiceYouCanImagineTester : Tester<DumbestServiceYouCanImagine>
{
[TestMethod]
public void WhenNumberIsZero_ReturnItsZero()
{
//Act
var result = Instance.Format(0);
//Assert
Assert.AreEqual("It's zero", result);
}
}
That's all well and good but what if your dumb service had dependencies to other services though?
public interface ISomeOtherService
{
public string UserId { get; }
public IReadOnlyList<int> Roles { get; }
}
public class DumbestServiceYouCanImagine
{
private readonly ISomeOtherService _someOtherService;
public DumbestServiceYouCanImagine(ISomeOtherService someOtherService)
{
_someOtherService = someOtherService;
}
public string DoSomeOtherStuff()
{
return _someOtherService.Roles.Contains(8) ?
$"User {_someOtherService.UserId} is authorized to do dumb stuff." :
$"User {_someOtherService.UserId} is strictly forbidden from doing dumb stuff!";
}
}
[TestClass]
public class DumbestServiceYouCanImagineTester : Tester<DumbestServiceYouCanImagine>
{
[TestMethod]
public void WhenContainsRoleNumberEight_SayThatUserIsAuthorized()
{
//Arrange
var userId = Fixture.Create<string>();
GetMock<ISomeOtherService>().Setup(x => x.UserId).Returns(userId);
GetMock<ISomeOtherService>().Setup(x => x.Roles).Returns(new List<int> { 8 });
//Act
var result = Instance.DoSomeOtherStuff();
//Assert
Assert.AreEqual($"User {userId} is authorized to do dumb stuff.", result);
}
[TestMethod]
public void WhenDoesNotContainRoleNumberEight_SayThatUserIsUnauthorized()
{
//Arrange
var userId = Fixture.Create<string>();
GetMock<ISomeOtherService>().Setup(x => x.UserId).Returns(userId);
GetMock<ISomeOtherService>().Setup(x => x.Roles).Returns(new List<int>());
//Act
var result = Instance.DoSomeOtherStuff();
//Assert
Assert.AreEqual($"User {userId} is strictly forbidden from doing dumb stuff!", result);
}
}
[AutoCustomization]
//This Customization will be applied project-wide so you don't have to remember to add them yourself each time in TestInitialize
[AutoCustomization]
public class SomeCustomization : ICustomization
{
...
}
//Also works with ISpecimenBuilder
[AutoCustomization]
public class SomeSpecimenBuilder : ISpecimenBuilder
{
...
}
Testing collections
Ever wanted to test whichever item from a collection?
[TestMethod]
public void WhenYouWantWhichever_GetWhichever()
{
//Arrange
var list = Fixture.CreateMany<string>().ToList();
var something = Fixture.Create<Something>();
GetMock<ISomeShadyService>().Setup(x => x.GetSomething(list.GetRandom())).Returns(something);
//Act
var result = Instance.DoSomething(list);
//Assert
result.Should.BeEquivalentTo(something);
}
You can also do the same thing but with the index only if that's what floats your boat.
var index = list.GetRandomIndex();
Using the generic tester with custom constructor parameters
It�s all well and good but what if you want to use the generic Tester class while providing your own parameters to the tested class� constructor instead of the automatically generated mocks and fixtures?
You can do that with the ConstructWith() method.
[AutoInject]
public class GameObjectFactory : IGameObjectFactory
{
private readonly IServiceProvider _serviceProvider;
public GameObjectFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IGameObject Create(GameObjectConfiguration configuration) => new GameObject(_serviceProvider, configuration);
}
public record GameObjectConfiguration(string Name, Vector2<float> InitialPosition, Direction InitialDirection);
//The service provider is passed by the GameObjectFactory and is always the same reference
//Configuration is unique to every instance so we need to be able to override it if we want to test that things are correctly initialized
public GameObject(IServiceProvider serviceProvider, GameObjectConfiguration configuration)
{
_game = serviceProvider.GetRequiredService<IGame>();
Name = configuration.Name;
Position = configuration.InitialPosition;
Direction = configuration.InitialDirection;
}
[TestClass]
public class GameObjectTester
{
[TestClass]
public class Move : Tester<GameObject>
{
[TestMethod]
public void Always_ChangePosition()
{
//Arrange
var configuration = Fixture.Create<GameObjectConfiguration>();
//It is important to call ConstructWith before accessing the Instance property!
ConstructWith(configuration);
//Act
Instance.Move(new Vector2<float>(1, 0));
//Assert
Instance.Position.Should().Be(configuration.InitialPosition + new Vector2<float>(1, 0));
}
}
}
AutoFillTester
Works just like Tester<T>
except that it automatically fills your Instance's public
set
and init
with values. Works in a lot of cases but you might want to stick with Tester<T>
for others.
Integration tests
The Eloquentest.Integration namespace (available on nuget.org as a separate package) provides tools to leverage MSTest to execute code without mocking all while using the Eloquentest structure and syntax you may already be familiar with.
IntegrationTester and IntegreationTester<T> replace Tester and Tester<T> and there are no mocks.
Setup
It works right out of the box if you already use AutoInject in your regular code.
Breaking changes
1.0.X → 1.1.X GetRandom and GetRandomIndex methods have been removed from Eloquentest. Please import and use ToolBX.OPEX from nuget.org instead.
2.0.X → 2.1.0
AutoFillTester<T>
was addded. There have been minor changes in when things are instantiated which may affect some users in Tester
and Tester<T>
.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net7.0
- AutoFixture (>= 4.18.0)
- Microsoft.Extensions.Options (>= 7.0.1)
- Moq (>= 4.20.69)
- MSTest.TestFramework (>= 3.1.1)
- ToolBX.AutoInject (>= 2.1.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on ToolBX.Eloquentest:
Package | Downloads |
---|---|
ToolBX.Eloquentest.Dummies
Package Description |
|
ToolBX.Eloquentest.AutoFixture
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.0.0 | 3,337 | 9/27/2024 |
3.0.0-beta4 | 300 | 9/22/2024 |
3.0.0-beta3 | 77 | 9/22/2024 |
3.0.0-beta2 | 127 | 9/7/2024 |
3.0.0-beta1 | 182 | 8/27/2024 |
2.2.1 | 3,930 | 1/17/2024 |
2.2.1-beta.1 | 67 | 1/14/2024 |
2.2.0 | 249 | 1/11/2024 |
2.2.0-beta97 | 167 | 1/7/2024 |
2.2.0-beta96 | 103 | 1/4/2024 |
2.2.0-beta94 | 122 | 12/29/2023 |
2.2.0-beta93 | 136 | 12/29/2023 |
2.2.0-beta92 | 102 | 12/29/2023 |
2.2.0-beta91 | 120 | 12/29/2023 |
2.2.0-beta9 | 148 | 12/14/2023 |
2.2.0-beta8 | 107 | 12/13/2023 |
2.2.0-beta7 | 140 | 11/24/2023 |
2.2.0-beta6 | 106 | 11/22/2023 |
2.2.0-beta5 | 108 | 11/22/2023 |
2.2.0-beta4 | 117 | 11/17/2023 |
2.2.0-beta3 | 100 | 11/17/2023 |
2.2.0-beta2 | 94 | 11/17/2023 |
2.2.0-beta11 | 133 | 12/27/2023 |
2.2.0-beta10 | 124 | 12/14/2023 |
2.2.0-beta1 | 108 | 11/17/2023 |
2.2.0-beta.12 | 85 | 12/28/2023 |
2.2.0-alpha.1 | 80 | 12/28/2023 |
2.1.4 | 2,761 | 11/22/2023 |
2.1.4-beta4 | 106 | 11/22/2023 |
2.1.4-beta3 | 115 | 11/17/2023 |
2.1.4-beta2 | 122 | 11/2/2023 |
2.1.4-beta1 | 105 | 10/28/2023 |
2.1.3 | 2,582 | 10/17/2023 |
2.1.3-beta1 | 103 | 10/17/2023 |
2.1.2 | 559 | 10/4/2023 |
2.1.2-beta7 | 145 | 10/3/2023 |
2.1.2-beta6 | 717 | 8/29/2023 |
2.1.2-beta5 | 109 | 8/28/2023 |
2.1.2-beta4 | 109 | 8/25/2023 |
2.1.2-beta3 | 119 | 8/24/2023 |
2.1.2-beta2 | 1,865 | 6/23/2023 |
2.1.2-beta1 | 134 | 6/22/2023 |
2.1.1 | 331 | 6/19/2023 |
2.1.0 | 258 | 6/13/2023 |
2.1.0-beta3 | 157 | 6/13/2023 |
2.1.0-beta2 | 134 | 6/12/2023 |
2.1.0-beta1 | 145 | 6/10/2023 |
2.0.2 | 978 | 4/25/2023 |
2.0.1 | 206 | 4/23/2023 |
2.0.0 | 410 | 11/9/2022 |
2.0.0-beta2 | 165 | 9/28/2022 |
2.0.0-beta1 | 161 | 9/20/2022 |
1.1.2 | 425 | 9/28/2022 |
1.1.1 | 432 | 9/20/2022 |
1.1.1-beta3 | 173 | 8/10/2022 |
1.1.1-beta2 | 149 | 8/10/2022 |
1.1.1-beta1 | 147 | 8/10/2022 |
1.1.0 | 407 | 8/10/2022 |
1.0.7 | 407 | 5/27/2022 |
1.0.6 | 419 | 5/16/2022 |
1.0.5 | 457 | 3/15/2022 |
1.0.5-beta | 167 | 3/15/2022 |
1.0.4 | 470 | 2/5/2022 |
1.0.3 | 436 | 2/4/2022 |
1.0.2 | 429 | 1/14/2022 |
1.0.1 | 265 | 12/22/2021 |
1.0.0 | 302 | 12/15/2021 |