2023/11/07 - Coenraad Stijne
When creating unit tests, object being tested either requires virtual
members, or an interface
.
Through the use of the Fody package, it is possible to manipulate the intermediate language (IL) during build, and make all concrete class members virtual
, so that they can be mocked without extra developer effort.
⚠️ This will not work for sealed
types. There is a Unsealed.Fody project, but it is unmaintained.
Package | Description |
---|---|
Fody | Extensible tool for weaving .net assemblies |
Virtuosity | Change all members to virtual. |
EmptyConstructor | Adds an empty constructor to classes even if you have a non-empty one defined. |
To enable Fody
, add the following to the Test .csproj
.
We configure it to only run in Debug
configurations, so that Release
builds remain unaffected.
<PropertyGroup>
...
<WeaverConfiguration Condition="'$(Configuration)' == 'Debug'">
<Weavers>
<Virtuosity />
<EmptyConstructor />
</Weavers>
</WeaverConfiguration>
</PropertyGroup>
public class Class1
{
private readonly Random _random;
public Class1(Random random)
{
_random = random;
}
public int GenerateRandomNumber() => _random.Next();
}
public class Class1
{
private readonly Random _random;
public Class1(Random random)
{
_random = random;
}
public Class1()
{
_random = random;
}
public virtual int GenerateRandomNumber() => _random.Next();
}
MSTest
+ Moq
example:[TestClass]
public class TestMethods
{
[TestMethod]
public void ConcreteClassMockTest()
{
var mock = new Mock<Class1>();
mock.Setup(e => e.GenerateRandomNumber()).Returns(1);
var result = mock.Object.GenerateRandomNumber();
Assert.AreEqual(1, result);
}
}