C# 单元测试中的.NET核心依赖项注入-具有多个具体实现的接口-Func<;字符串,i接口>;

C# 单元测试中的.NET核心依赖项注入-具有多个具体实现的接口-Func<;字符串,i接口>;,c#,unit-testing,.net-core,dependency-injection,moq,C#,Unit Testing,.net Core,Dependency Injection,Moq,我需要你的帮助,让单元测试方法在.net核心控制台应用程序中与Moq一起工作。 道歉,如果有人问我,但我试过了,却找不到答案 有三个类实现一个接口 public class MailNotification : ISendNotification { public bool SendNotification() { return true; } } public class EmailNotification : ISendNotification {

我需要你的帮助,让单元测试方法在.net核心控制台应用程序中与Moq一起工作。 道歉,如果有人问我,但我试过了,却找不到答案

有三个类实现一个接口

public class MailNotification : ISendNotification
{
    public bool SendNotification()
    {
        return true;
    }
}

public class EmailNotification : ISendNotification
{
    public bool SendNotification()
    {
        return true;
    }
}

public class SmsNotification : ISendNotification
{
    public bool SendNotification()
    {
        return true;
    }
 }
在Program.cs文件中,我们有:

        private static IServiceCollection ConfigureServices()
    {
        IServiceCollection services = new ServiceCollection();

        var config = LoadConfiguration();
        services.AddSingleton(config);

        services.AddTransient<IUser, User>();
        services.AddTransient<Something>();
        services.AddTransient<MailNotification>();
        services.AddTransient<EmailNotification>();
        services.AddTransient<SmsNotification>();

        //multiply concrete implementation of an Interface
        services.AddTransient<Func<string, ISendNotification>>(serviceProvider => key =>
        {
            switch (key)
            {
                case "Mail":
                    return serviceProvider.GetService<MailNotification>();
                case "Email":
                    return serviceProvider.GetService<EmailNotification>();
                default:
                    return serviceProvider.GetService<SmsNotification>();
            }
        });

        return services;
    }
专用静态IServiceCollection配置服务()
{
IServiceCollection服务=新的ServiceCollection();
var config=LoadConfiguration();
services.AddSingleton(config);
services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
services.AddTransient();
//接口的具体实现
services.AddTransient(serviceProvider=>key=>
{
开关(钥匙)
{
案例“邮件”:
返回serviceProvider.GetService();
案例“电子邮件”:
返回serviceProvider.GetService();
违约:
返回serviceProvider.GetService();
}
});
返回服务;
}
类的某些内容如下所示:

    public class Something
{
    private readonly IConfiguration config;
    private readonly IUser user;
    private readonly Func<string, ISendNotification> sendMsg;

    public Something(IConfiguration config, IUser user, Func<string, ISendNotification>  send)
    {
        this.config = config;
        this.user = user;
        this.sendMsg = send;
    }

    public bool ProcessUser()
    {
        bool result;
        switch (user.PreferredCommunication.ToString())
        {
            case "Mail":
                  result = sendMsg(NotificationType.Mail.ToString()).SendNotification();
                break;
            case "Email":
                  result = sendMsg(NotificationType.Email.ToString()).SendNotification();
                break;

            default:
                result = sendMsg (NotificationType.SMS.ToString()).SendNotification();
                break;
        }

        return result;
    }
}
公共类
{
私有只读IConfiguration配置;
专用只读IUser用户;
私有只读Func sendMsg;
公共内容(IConfiguration配置、IUser用户、Func发送)
{
this.config=config;
this.user=用户;
this.sendMsg=send;
}
公共bool ProcessUser()
{
布尔结果;
开关(user.PreferredCommunication.ToString())
{
案例“邮件”:
结果=sendMsg(NotificationType.Mail.ToString()).SendNotification();
打破
案例“电子邮件”:
结果=sendMsg(NotificationType.Email.ToString()).SendNotification();
打破
违约:
结果=sendMsg(NotificationType.SMS.ToString()).SendNotification();
打破
}
返回结果;
}
}
这是单元测试类

    public class UnitTest1
{
    private readonly ITestOutputHelper outPutHelper;
    private readonly IConfiguration config;

    public UnitTest1(ITestOutputHelper helper)
    {
        this.outPutHelper = helper;
        //get path to appsettings file, assembly location
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        string projectPath = Path.GetDirectoryName(path);

        config = new ConfigurationBuilder().SetBasePath(projectPath).AddJsonFile("appsettings.json").Build();

    }
    [Fact]
    [Trait("Category", "Unit")]
    public void ProcessUser_MailNotification_True()
    {
        //Arrange
        Mock<ISendNotification> mockNotify = new Mock<ISendNotification>();
        mockNotify.Setup(x => x.SendNotification()).Returns(true);
        Mock<IUser> mockUser = new Mock<IUser>();
        mockUser.Setup(x => x.TruncateName(It.IsAny<string>()));

        Func<string, ISendNotification> func = () => {
            return new Mock<"Mail", ISendNotification>();
        }; //< -- help help here 
           //The error is Delegate'Func<string, ISendNotification>' does not take 0 arguments

        //Act
        var sut = new Something(config, mockUser.Object, mockNotify.Object); //< -- help help here 
        //The error is Arugment 3: cannot convert from 'ISendNotification' to System.Func<string, ISendNotification>'
    }
}
公共类UnitTest1
{
私有只读ITestOutputHelper outPutHelper;
私有只读IConfiguration配置;
公共单元测试1(ITestOutputHelper)
{
this.outPutHelper=helper;
//获取appsettings文件的路径,程序集位置
字符串codeBase=Assembly.getExecutionGassembly().codeBase;
UriBuilder uri=新的UriBuilder(代码库);
字符串路径=Uri.UnescapeDataString(Uri.path);
字符串projectPath=Path.GetDirectoryName(路径);
config=new ConfigurationBuilder().SetBasePath(projectPath).AddJsonFile(“appsettings.json”).Build();
}
[事实]
[特征(“类别”、“单位”)]
public void ProcessUser\u MailNotification\u True()
{
//安排
Mock mockNotify=new Mock();
mockNotify.Setup(x=>x.SendNotification())。返回(true);
Mock mockUser=new Mock();
mockUser.Setup(x=>x.TruncateName(It.IsAny());
Func Func=()=>{
返回新的Mock();
}//<--请帮忙
//错误是委托“Func”不接受0个参数
//表演
var sut=newsomething(配置、mockUser.Object、mockNotify.Object);//<--此处的帮助
//错误为分段3:无法从“ISendNotification”转换为System.Func
}
}

非常感谢你的帮助

未正确声明委托

//...

Func<string, ISendNotification> send = (string key) => mockNotify.Object;

//...
从那里可以执行测试来断言预期的行为

//...

//Act
bool actual = sut.ProcessUser();

//Assert - FluentAssertions
actual.Should().BeTrue();
但基于被测成员内部使用的依赖关系

//...

switch (user.PreferredCommunication.ToString())

//...

需要进一步设置,以允许被测构件流动至完工。但是,由于原始问题中没有提供该细节,因此我无法指定该值应该是什么。

未正确声明该委托

//...

Func<string, ISendNotification> send = (string key) => mockNotify.Object;

//...
从那里可以执行测试来断言预期的行为

//...

//Act
bool actual = sut.ProcessUser();

//Assert - FluentAssertions
actual.Should().BeTrue();
但基于被测成员内部使用的依赖关系

//...

switch (user.PreferredCommunication.ToString())

//...

需要进一步设置,以允许被测构件流动至完工。但由于原始问题中未提供该细节,我无法指定该值应为多少。

您是否认为您的问题标题“总结了具体问题”?对我来说,它只提供了一些关于你的问题的无关紧要的信息。事实上,我正在努力找到这个问题。你能澄清一下你到底需要什么帮助吗?@Llama,很抱歉搞混了。我猜除了“编译单元测试并进入测试中的方法”之外,很难说需要什么,但我知道它的要点。多亏了恩科西,他认为委托人的申报是不正确的。谢谢我刚刚意识到您在代码中包含了错误详细信息。我以前略读你的问题时没有看到这一点。我很高兴恩科西看到了它,并能帮助你。:)你会说你的题目“概括了具体问题”吗?对我来说,它只提供了一些关于你的问题的无关紧要的信息。事实上,我正在努力找到这个问题。你能澄清一下你到底需要什么帮助吗?@Llama,很抱歉搞混了。我猜除了“编译单元测试并进入测试中的方法”之外,很难说需要什么,但我知道它的要点。多亏了恩科西,他认为委托人的申报是不正确的。谢谢我刚刚意识到您在代码中包含了错误详细信息。我以前略读你的问题时没有看到这一点。我很高兴恩科西看到了它,并能帮助你。:)