.NET Core如何进行单元测试服务?

wtf512

我已经构建了一个WebAPI,并且想要创建一个单元测试项目来自动测试我的服务。

我的WebAPI的流程很简单:

控制器(DI服务)->服务(DI存储库)-> _repo CRUD

假设我有一个类似的服务:

public int Cancel(string id) //change status filed to 'n'
{
    var item = _repo.Find(id);
    item.status = "n";
    _repo.Update(item);
    return _repo.SaveChanges();
}

我想构建一个单元测试,仅使用InMemoryDatabase。

public void Cancel_StatusShouldBeN() //Testing Cancel() method of a service
{
    _service.Insert(item); 

    int rs = _service.Cancel(item.Id);
    Assert.Equal(1, rs);

    item = _service.GetByid(item.Id);
    Assert.Equal("n", item.status);
}

我搜索了其他相关问题,发现

您不能在测试类上使用依赖项注入。

我只是想知道是否还有其他解决方案可以实现我的单元测试想法?

在进行单元测试时,您应该只提供要测试的类的所有依赖项。那就是依赖注入;没有让服务自行构造其依赖项,而是使其依赖于外部组件来提供它们。当你之外的依赖注入容器和单元测试,其中里面手动创建你测试的类,它是你的责任,提供的依赖关系。

实际上,这意味着您可以向构造函数提供模拟或实际对象。例如,您可能想要提供一个真正的记录器,但没有目标,具有连接的内存数据库的真实数据库上下文或某些模拟服务。

在此示例中,假设您正在测试的服务如下所示:

public class ExampleService
{
    public ExampleService(ILogger<ExampleService> logger,
        MyDbContext databaseContext,
        UtilityService utilityService)
    {
        // …
    }
    // …
}

因此,为了进行测试ExampleService,我们需要提供这三个对象。在这种情况下,我们将对每个对象执行以下操作:

  • ILogger<ExampleService>–我们将使用没有附加目标的真实记录器。因此,对记录器的任何调用都可以正常工作,而无需我们提供一些模拟,但是我们不需要测试日志输出,因此我们不需要真正的目标
  • MyDbContext –在这里,我们将使用真实的数据库上下文以及附加的内存数据库
  • UtilityService –为此,我们将创建一个模拟,该模拟将在需要测试的方法中设置所需的实用程序方法。

因此,单元测试可能如下所示:

[Fact]
public async Task TestExampleMethod()
{
    var logger = new LoggerFactory().CreateLogger<ExampleService>();
    var dbOptionsBuilder = new DbContextOptionsBuilder().UseInMemoryDatabase();

    // using Moq as the mocking library
    var utilityServiceMock = new Mock<UtilityService>();
    utilityServiceMock.Setup(u => u.GetRandomNumber()).Returns(4);

    // arrange
    using (var db = new MyDbContext(dbOptionsBuilder.Options))
    {
        // fix up some data
        db.Set<Customer>().Add(new Customer()
        {
            Id = 2,
            Name = "Foo bar"
        });
        await db.SaveChangesAsync();
    }

    using (var db = new MyDbContext(dbOptionsBuilder.Options))
    {
        // create the service
        var service = new ExampleService(logger, db, utilityServiceMock.Object);

        // act
        var result = service.DoSomethingWithCustomer(2);

        // assert
        Assert.NotNull(result);
        Assert.Equal(2, result.CustomerId);
        Assert.Equal("Foo bar", result.CustomerName);
        Assert.Equal(4, result.SomeRandomNumber);
    }
}

在您的特定Cancel情况下,您要避免使用当前未测试的服务的任何方法。因此,如果要测试Cancel,则应该从服务中调用的唯一方法是Cancel一个测试可能看起来像这样(只是在这里猜测依赖项):

[Fact]
public async Task Cancel_StatusShouldBeN()
{
    var logger = new LoggerFactory().CreateLogger<ExampleService>();
    var dbOptionsBuilder = new DbContextOptionsBuilder().UseInMemoryDatabase();

    // arrange
    using (var db = new MyDbContext(dbOptionsBuilder.Options))
    {
        // fix up some data
        db.Set<SomeItem>().Add(new SomeItem()
        {
            Id = 5,
            Status = "Not N"
        });
        await db.SaveChangesAsync();
    }

    using (var db = new MyDbContext(dbOptionsBuilder.Options))
    {
        // create the service
        var service = new YourService(logger, db);

        // act
        var result = service.Cancel(5);

        // assert
        Assert.Equal(1, result);
    }

    using (var db = new MyDbContext(dbOptionsBuilder.Options))
    {
        var item = db.Set<SomeItem>().Find(5);
        Assert.Equal(5, item.Id);
        Assert.Equal("n", item.Status);
    }
}

顺便说一句。请注意,我一直在打开新的数据库上下文,以避免从缓存的实体中获取结果。通过打开新的上下文,我可以验证所做的更改是否确实将其完全放入数据库中。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在对.Net core 3.1后台服务进行单元测试时,无法解析IConfiguration

如何对ASP.NET Core Web应用程序(.Net Framework)进行单元测试?

如何初始化IOption <AppSettings>以对.NET核心MVC服务进行单元测试?

如何使用Moq对在.NET中使用asmx服务的应用程序进行单元测试

.NET Core中的单元测试托管服务

使用Moq .net Core进行单元测试文件上传

Net Core:如何使用数据库行简化单元测试存储库和服务

如何在 ASP.NET Core 中使用 mysql 进行单元测试、actionresult

如何在 .NET Core 3.1 中对使用 ExecuteSqlRawAsync 调用存储过程的函数进行单元测试?

如何使用Moq对.NET Core 3.1中的LoggerMessage.Define()进行单元测试?

如何在 .Net Core 中对 ADF PipeLineRun 进行单元测试?

如何在ASP.NET Core中使用ILogger进行单元测试

如何对.NET Core中的Startup.cs进行单元测试

如何在ASP.NET Core中对ViewBag进行单元测试?

如何使用依赖注入.net Core 2进行单元测试

如何在ASP.NET Core MVC中对RazorViewEngineOptions进行单元测试?

如何对返回匿名对象的ASP.NET Core MVC控制器进行单元测试?

如何对每个订阅的 Rx.Net 进行单元测试

如何在ASP.NET Core 1.1中对使用HttpContext的MVC控制器进行单元测试

如何在ASP.NET Core中对Web API的动作过滤器属性进行单元测试?

通过隔离所需的Web服务来对ac#.Net Web服务进行单元测试

是否应针对.NET标准库而不是.NET Core的框架进行单元测试项目?

如何进行单元测试

在使用 xunit 和 .net core 3.1 进行单元测试时获取记录器

在ASP.NET Core中对自定义密码验证器进行单元测试

模拟ASP.NET Core中的User.Identity以进行单元测试

是否可以在.net core中对F#项目进行单元测试?

使用JWT声明对.NET Core Web API控制器进行单元测试

在.Net Core中对BackgroundService进行单元测试时要声明或验证的内容