您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Moq被遗忘的功能

寒冰屋 发布时间:2020-06-07 16:29:42 ,浏览量:0

目录

介绍

背景

使用代码

兴趣点

介绍

给出了如何经常使用Moq以及如何改进这种工作方式的解释。

背景

如果您对.NET Core中的xUnit,模拟和固定装置(fixtures)有一定的经验,这将非常有帮助。此处显示的测试是针对.NET Core编写的,但是大多数代码都可以在使用其他单元测试框架的情况下使用。如果您不熟悉固定装置(fixtures),建议阅读这篇文章。如果您不熟悉Moq,建议阅读此文章。

使用代码

我们从要测试的代码开始:

[HttpGet("{queryEntry}", Name = "GetNumberOfCharacters")]
public async Task GetNumberOfCharacters(string queryEntry)
{
    var numberOfCharacters = 
        await _searchEngineService.GetNumberOfCharactersFromSearchQuery(queryEntry);
    return Ok(numberOfCharacters);
}

使用AutoFixture.AutoMoq(NuGet软件包在此处)可以轻松进行单元测试。使用测试的安排(arrange)部分中的Freeze方法创建模拟并进行验证,并使用Verify 方法在测试结束时进行模拟。在两者之间调用Create方法以创建包含我们要测试的方法的实例。代码如下所示:

[Fact]
public async Task GetTest()
{
    // arrange
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var service = fixture.Freeze();
    service.Setup(a => a.GetNumberOfCharactersFromSearchQuery(It.IsNotNull()))
        .ReturnsAsync(8);

    var controller = fixture.Build().OmitAutoProperties().Create();

    // act
    var response = await controller.GetNumberOfCharacters("Hoi");

    // assert
    Assert.Equal(8, ((OkObjectResult)response.Result).Value);
    service.Verify(s => s.GetNumberOfCharactersFromSearchQuery("Hoi"), Times.Once);
}

另外,我们可以创建一个集成测试(而不是仅一个单元测试),该集成测试仅解析Startup类中设置的所有依赖项,并替换我们要模拟的单个依赖项。主要优点是我们可以获得更好的代码覆盖率(因为Startup类和Program类被触发)。主要缺点是我们的隔离度较低,因此通常不会替代单元测试。可以使用IntegrationFixture(NuGet包在此处)完成,这就是代码的样子:

[Fact]
public async Task GetTestFreeze()
{
    // arrange
    await using (var fixture = new Fixture())
    {
        var service = fixture.Freeze();
        service.Setup(a => a.GetNumberOfCharactersFromSearchQuery(It.IsNotNull()))
            .ReturnsAsync(8);

        var controller = fixture.Create();

        // act
        var response = await controller.GetNumberOfCharacters("Hoi");

        // assert
        Assert.Equal(8, ((OkObjectResult) response.Result).Value);
        service.Verify(s => s.GetNumberOfCharactersFromSearchQuery("Hoi"), Times.Once);
    }
}

这段代码看起来不错,但是在两个测试中都出错了。我们没有验证是否对模拟进行了其他任何调用。这听起来可能无关紧要,但事实并非如此。其他调用可能仅引起副作用,而副作用通常是导致生产问题的主要原因。这是两个测试结束时所需的额外代码:

service.VerifyNoOtherCalls();

很容易忘记这一点。Moq 4.7自动附带了AutoFixture.AutoMoq不支持此方法的文件。为了能够调用它,需要单独安装一个更新的版本(至少4.8)。此外, Moq版本本身没有附带IntegrationFixture,因此对于这种情况,您需要单独安装。这种方法确实有助于防止副作用,但很容易忘记。如果您想查看所有代码:它位于GitHub上。

兴趣点

我很难学到这种方法。我发现了一个由实际副作用引起的实际生产问题,以防万一我会使用VerifyNoOtherCalls方法。希望本文能帮助您避免犯同样的错误。

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0878s