C# 如何测试使用反射在不同类上调用方法的方法是否调用了正确的类

C# 如何测试使用反射在不同类上调用方法的方法是否调用了正确的类,c#,.net-core,moq,xunit,C#,.net Core,Moq,Xunit,我有一个服务,它基于通过反射找到的类属性,在不同的类上调用Invoke方法。我想测试是否实例化了正确的类并调用了方法 服务: private void InvokeCorrectClass(string message) { //find type from cache of types based on info in message //_cacheTypes is Dictionary<Type, string> var type = _cacheTyp

我有一个服务,它基于通过反射找到的类属性,在不同的类上调用Invoke方法。我想测试是否实例化了正确的类并调用了方法

服务:

private void InvokeCorrectClass(string message)
{
    //find type from cache of types based on info in message
    //_cacheTypes is Dictionary<Type, string>
    var type = _cacheTypes.First(p=>p.Value == msg.MessageType).Key;
    var instance = Activator.CreateInstance(type);
    var invokeMethod = type.GetMethod("Invoke");

    invokeMethod.Invoke(instance, new object[] {msg, messageId});
}
第2类:

public async Task Invoke(object message, int messageId)
{
    //process MessageType 2
}
我知道代码工作正常,因为我使用断点找到了正确的代码,但我试图使用Moq和XUnit来自动创建和调用正确的类,我一点运气都没有

另外,类1或类2都没有无参数构造函数,并且有很多依赖项。我已尝试添加一个无参数构造函数,以便可以通过设置模拟它:

_testModule.MessageProcessorMock.Setup(i => i.Invoke(It.IsAny<object>, It.IsAny<int>()))
                .Returns<object, int>((msg, messageId) =>
                {
                    msgId = messageId;
                    msgPassedOn = msg;
                    return Task.CompletedTask;
                });
\u testModule.MessageProcessorMock.Setup(i=>i.Invoke(It.IsAny,It.IsAny()))
.Returns((msg,messageId)=>
{
msgId=messageId;
msgPassedOn=msg;
返回Task.CompletedTask;
});

但它从未被调用。

与其模拟和检查某些方法是否被调用,不如测试预期的行为是否被执行。使用反射调用的方法是什么?测试这一点。我尝试做更多的单元测试,而不是集成测试,模拟调用方法的响应将允许我返回,而无需对所有依赖项进行所有设置。不要专注于术语(单元或集成),所有测试都只是测试,它们提供对生产代码的反馈。只模拟缓慢(外部资源)和非常复杂的依赖项。测试中的模拟越少,测试越有价值。另一种方法:编写测试时的挣扎可能是当前方法不“可测试/可模拟”的标志。您可以更改代码以使其更“单元”可测试(到处都是接口),也可以少模拟并使用“集成”测试来覆盖“困难”的逻辑。另一种方法是:如果您可以更改代码并将缓存类型作为测试下类的依赖项传递。然后在测试中,您可以传递自己的缓存类型,这将很容易断言调用了正确的类。
_testModule.MessageProcessorMock.Setup(i => i.Invoke(It.IsAny<object>, It.IsAny<int>()))
                .Returns<object, int>((msg, messageId) =>
                {
                    msgId = messageId;
                    msgPassedOn = msg;
                    return Task.CompletedTask;
                });