NUnit测试项目的.NET核心容器定义

时间:2018-11-08 17:10:46

标签: c# dependency-injection .net-core nunit ioc-container

.NET Core我还很陌生。我想知道的是如何在NUnit类库项目中定义DI容器。我知道它是通过IServiceCollection完成的,但是由于没有Startup方法,所以我不知道从何处获取实现此接口的实例。

我还希望能够从其他类库(正在测试的主题)中加载定义。这应该更简单,因为我可以在一个类库中使用一个IServiceCollection参数来创建一个静态方法,但是同样,如何获得它呢?

另一个问题是,我认为可以出于测试目的而模拟某些接口,但是我似乎不明白如何替换已经使用IServiceCollection的方法创建的映射,例如AddSingletonAddTransient。有一种Remove方法,但没有记录。

谢谢Radek

2 个答案:

答案 0 :(得分:2)

IServiceCollectionServiceCollecion类实现。因此,如果要对集成测试执行此操作,则可以使用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的快速入门指南