c# - 单元测试中的 .NET Core 依赖注入 - 具有多个具体实现的接口 - Func
问题描述
我需要您的帮助,以使单元测试方法在 .net Core 控制台应用程序中与 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;
}
某些类看起来像这样:
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;
}
}
这是单元测试类
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>'
}
}
非常感谢您的帮助!
解决方案
未正确声明委托
//...
Func<string, ISendNotification> send = (string key) => mockNotify.Object;
//...
而delegate也是需要传递给被测对象的
//...
var sut = new Something(config, mockUser.Object, send);
//...
从那里可以执行测试以断言预期的行为
//...
//Act
bool actual = sut.ProcessUser();
//Assert - FluentAssertions
actual.Should().BeTrue();
但是根据被测成员中使用的依赖关系,
//...
switch (user.PreferredCommunication.ToString())
//...
需要进一步的设置以允许被测成员流动到完成。但是由于原始问题中没有提供该详细信息,因此我将无法指定该值应该是什么。
推荐阅读
- php - 有没有办法计算音频按钮被单击的次数并使用 ajax 调用将其保存到数据库中?
- paypal - 我可以在 paypal api 的帮助下向我的 paypal 帐户付款吗
- android - 如何从解析服务器获取应用程序 ID?我找不到文件“Server.js”
- c++ - 计算二叉搜索树中的唯一值
- ios - 如何在 App Store 中构建、提交和添加 macOS 版本到 iOS 应用程序?
- assembly - 部分与段?
- python - 取消所有异步任务/不和谐 py 循环
- fortran - 使用 LAPACK 的 DORMQR 和非方形 Q
- java - 为什么 toLowerCase 不将字符串元素转换为小写?
- javascript - javascript: css 没有解决,为什么?