我想对由依赖项引发的事件是否由被测类进行预订进行单元测试。要设置上下文,我具有以下接口和类。
ITestedService.cs
public interface ITestedService
{
Task Start();
Task Stop();
}
IDependency.cs
public interface IDependency
{
event EventHandler<SoAndSoEventArgs> SomethingHappened;
Task Start();
Task Stop();
}
ISecondDependency
public interface ISecondDependency
{
Task DoYourJob(SoAndSo soAndSo);
}
TestedService.cs
public class TestedService
{
readonly IDependency m_dependency;
readonly ISecondDependency m_secondDependency;
public TestedService(
IDependency dependency,
ISecondDependency secondDependency)
{
m_dependency = dependency;
m_secondDependency = secondDependency;
}
public async Task Start()
{
m_dependency.SomethingHappened += OnSomethingHanppened;
await m_dependency.Start();
}
private async void OnSomethingHanppened(object sender, SoAndSoEventArgs args)
{
SoAndSo soAndSo = SoAndSoMapper.MapToDTO(args);
await m_secondDependency.DoYourJob(soAndSo),
}
}
在上述情况下,我想使用Start()
对TestedService
类的xUnit
方法进行单元测试。我想知道如何:
IDependency.SomethingHappened
被触发。OnSomethingHappened
方法ISecondDependency.DoYourJob(soAndSo)
。单元测试的目的可以是:
话虽如此,您无需测试语言的内部。例如,在这种情况下,您不需要验证注册事件时是否将调用注册的方法。这是语言的工作。通过语言测试。
因此,您确认Start方法执行了预期的调用。顺便说一句,如上所述,只有在有理由这样做时才有意义,例如上面的目的2。现在您知道OnSomethingHappened将被触发。语言保证了这一点。您要测试的是OnSomethingHappened中的实际实现。为此,您需要通过使其可访问(访问修饰符private不起作用)并使其依赖关系也可模拟(SoAndSoMapper不可模拟),使该方法更具可测试性。
注:单元测试更多是使代码可测试的活动,而不是弄清楚如何编写测试的活动。如果编写测试很困难,则可能表明代码不容易测试。
public class TestedService
{
readonly IDependency m_dependency;
readonly ISomethingDoer m_somethingDoer;
public TestedService(
IDependency dependency,
ISomethingDoer somethingDoer)
{
m_dependency = dependency;
m_somethingDoer = somethingDoer;
}
public async Task Start()
{
m_dependency.SomethingHappened += m_somethingDoer.OnSomethingHanppened;
await m_dependency.Start();
}
}
interface ISomethingDoer
{
Task OnSomethingHanppened(object sender, SoAndSoEventArgs args);
}
class SomethingDoer : ISomethingDoer
{
readonly ISecondDependency m_secondDependency;
readonly ISoAndSoMapper m_soAndSoMapper;
public SomethingDoer(ISecondDependency secondDependency, ISoAndSoMapper soAndSoMapper)
{
m_secondDependency = secondDependency;
m_soAndSoMapper = soAndSoMapper;
}
public async Task OnSomethingHanppened(object sender, SoAndSoEventArgs args)
{
SoAndSo soAndSo = m_soAndSoMapper.MapToDTO(args);
await m_secondDependency.DoYourJob(soAndSo),
}
}
现在,您可以通过为SomethingDoer创建一个测试类,模拟它的依赖关系并验证例如给定的soAndSoMapper模拟返回了某个值,然后使用该值调用secondDependency来测试OnSomethingHappened的功能。尽管再次,OnSomethingHappened并没有做太多事情。因此,是否要进行测试是有争议的。