我就是这样做的。在 UnitTest 类上有一个内部嵌套类。
请注意“MyAbstractClass.GetABoolean”方法。指出抽象类如何依赖于子类的实现。
namespace MyCompany.MyProject.UnitTests
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FluentAssertions;
[TestClass]
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public class MyAbstractClassTests
{
[TestMethod]
public void ConstructorILoggerFactoryIsNullTest()
{
Action a = () => new MyUnitTestConcreteClass(null);
a.Should().Throw<ArgumentNullException>().WithMessage(MyAbstractClass<int>.ErrorMessageILoggerFactoryIsNull);
}
[TestMethod]
public void GetABooleanIsTrueTest()
{
/* here is more likely what you want to test..an implemented method on the abstract class */
Mock<ILoggerFactory> iloggerFactoryMock = this.GetDefaultILoggerFactoryMock();
MyUnitTestConcreteClass testItem = new MyUnitTestConcreteClass(iloggerFactoryMock.Object);
Assert.IsTrue(testItem.GetABoolean());
}
[TestMethod]
public void GetSomeIntsIsNotNullTest()
{
/* you may not want to test the abstract methods, but you can */
Mock<ILoggerFactory> iloggerFactoryMock = this.GetDefaultILoggerFactoryMock();
MyUnitTestConcreteClass testItem = new MyUnitTestConcreteClass(iloggerFactoryMock.Object);
Assert.IsNotNull(testItem.GetSomeInts());
}
private Mock<ILoggerFactory> GetDefaultILoggerFactoryMock()
{
Mock<ILoggerFactory> returnMock = new Mock<ILoggerFactory>(MockBehavior.Strict);
////returnMock.Setup(x => x.SomeBooleanMethod()).Returns(true);
return returnMock;
}
internal class MyUnitTestConcreteClass : MyAbstractClass<int>
{
internal MyUnitTestConcreteClass(ILoggerFactory loggerFactory) : base(loggerFactory)
{
}
public override ICollection<int> GetSomeInts()
{
return new List<int> { 111, 222, 333 };
}
}
}
}
和下面的“真实”抽象类
public abstract class MyAbstractClass<T> : where T : struct
{
public const string ErrorMessageILoggerFactoryIsNull = "ILoggerFactory is null";
public WhiteListStepBodyAsyncBase(ILoggerFactory loggerFactory)
{
if (null == loggerFactory)
{
throw new ArgumentNullException(ErrorMessageILoggerFactoryIsNull, (Exception)null);
}
}
public bool GetABoolean()
{
/* note , this is important factor (sometimes), here this implemented method DEPENDS on an abstract method , and why I have the code "return new List<int> { 111, 222, 333 };" above .. see the connection ?? */
return this.GetSomeInts().Count > 0;
}
public abstract ICollection<int> GetSomeInts();
}
这个问题比较老,但是原理都是一样的。
这是我的 VS2019,2020 年 .. 包导入。
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.8.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="5.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
</ItemGroup>