.NET Core我还很陌生。我想知道的是如何在NUnit类库项目中定义DI容器。我知道它是通过IServiceCollection
完成的,但是由于没有Startup方法,所以我不知道从何处获取实现此接口的实例。
我还希望能够从其他类库(正在测试的主题)中加载定义。这应该更简单,因为我可以在一个类库中使用一个IServiceCollection
参数来创建一个静态方法,但是同样,如何获得它呢?
另一个问题是,我认为可以出于测试目的而模拟某些接口,但是我似乎不明白如何替换已经使用IServiceCollection
的方法创建的映射,例如AddSingleton
或AddTransient
。有一种Remove
方法,但没有记录。
谢谢Radek
答案 0 :(得分:2)
IServiceCollection
由ServiceCollecion
类实现。因此,如果要对集成测试执行此操作,则可以使用ServiceCollection
类来创建自己的ServiceProvider
。
var services = new ServiceCollection();
services.AddTransient<IMyInterface, MyClass>();
services.AddScoped<IMyScopedInteface, MyScopedClass>();
...
var serviceProvider = sc.BuildServiceProvider();
您现在可以在测试中使用serviceProvider
实例来获取您的课程:
var myClass = serviceProvider.GetService<IMyInterface>();
如果您要模拟某些接口而不是使用真实的接口,则可以将模拟添加,而不是将真实的类/接口添加到服务集合中:
mockInterface = new Mock<IMyInterface>();
sc.AddScoped<IMyInterface>(factory => mockInterface.Object);
答案 1 :(得分:1)
通常,您不想为测试创建DI容器,但是,正如您意识到的那样,您想模拟它们。因此,例如,如果这是您要测试的课程:
public class UserService
{
private readonly IUserDatabase _userDatabase;
public UserService(IUserDatabase userDatabase)
{
_userDatabase = userDatabase;
}
public bool DoesUserExist(int userId)
{
return _userDatabase.UserExists(userId);
}
}
这是使用的接口的定义:
public interface IUserDatabase
{
bool UserExists(int userId);
}
在测试中,我们可以模拟接口以返回测试所需的特定值:
[TestClass]
public class UserServiceTests
{
[TestMethod]
public void DoesUserExist_ForValidUserId_ReturnsTrue()
{
var fakeUserId = 123;
var mockUserDatabase = new Mock<IUserDatabase>();
mockUserDatabase.Setup(udb => udb.UserExists(fakeUserId)).Returns(true);
var userService = new UserService(mockUserDatabase.Object);
var result = userService.DoesUserExist(fakeUserId);
Assert.IsTrue(result);
mockUserDatabase.VerifyAll();
}
}
因此,在此测试中,我们使用Moq
创建了接口的模拟。我们不需要使用DI容器,因为我们处于创建要测试的类的控制器中。 DI容器在生产中使用更多,因为它使应用程序可以创建所需的任何依赖关系,而无需调用代码new
-如果要对单元进行类测试,这是一个大问题。>
.VerifyAll()
方法检查在模拟对象上设置的所有方法(在这种情况下,我们设置了对UserExists
的调用)是否都确实被调用。
关于如何使用Moq
和模拟接口的例子很多。
here
Moq
的快速入门指南