You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试用例单独运行正常但批量执行失败求助

单元测试单独运行正常,批量运行失败的排查求助

我有一个单元测试用例,单独运行时正常,但所有测试一起运行时失败。尝试过添加Thread.Sleep()、将方法改为同步调用,都没有效果。

运行错误信息

Assert.Equal() Failure: Values differ
Expected: 2
Actual: 4

失败的测试代码

[Fact]
public async Task Should_Trigger_PublishLocationWac_Function()
{
    //Arrange
    PrepareData(out List<LocationWac> locationWacData, out SkuAndWac skuAndWac);

    Arrange(locationWacData);

    //Act
    var result = await _handler.RunAsync(skuAndWac, _mockContext.Object);

    //Assert
    Assert.Equal(locationWacData.Count, result.TotalDocuments);
    Assert.Equal(locationWacData.Count, result.TotalPublished);
}

private void Arrange(List<LocationWac> oneWacData, bool IsPublishedFailed = false, bool isException = false)
{
    Environment.SetEnvironmentVariable(ConfigConstants.BatchSize, oneWacData.Count.ToString());

    _mockloggerFactory.Setup(p => p.CreateLogger(It.IsAny<string>())).Returns(_mockLogger.Object);
    _mockServiceProvider.Setup(p => p.GetService(It.IsAny<Type>())).Returns(_mockloggerFactory.Object);
    _mockContext.Setup(p => p.InstanceServices).Returns(_mockServiceProvider.Object);

    var cursorMock = new Mock<IAsyncCursor<LocationWac>>();
    cursorMock.SetupSequence(x => x.MoveNext(It.IsAny<CancellationToken>()))
        .Returns(true)
        .Returns(false);
    cursorMock.SetupSequence(x => x.MoveNextAsync(It.IsAny<CancellationToken>()))
        .ReturnsAsync(true)
        .ReturnsAsync(false);
    cursorMock.SetupGet(x => x.Current).Returns(oneWacData);

    if (isException)
    {
        _mockLocationWacRepository.Setup(x => x.GetCollection().FindAsync(It.IsAny<FilterDefinition<LocationWac>>(), It.IsAny<FindOptions<LocationWac, LocationWac>>(), default))
            .ThrowsAsync(new Exception("Test exception"));
    }
    else
    {
        _mockLocationWacRepository.Setup(x => x.GetCollection().FindAsync(It.IsAny<FilterDefinition<LocationWac>>(), It.IsAny<FindOptions<LocationWac, LocationWac>>(), default))
            .ReturnsAsync(cursorMock.Object);
    }

    if (IsPublishedFailed)
    {
        _mockMessageProducer.Setup(x => x.Produce(It.IsAny<List<string>>(), It.IsAny<string>()))
            .ReturnsAsync(0);
    }
    else
    {
        _mockMessageProducer.Setup(x => x.Produce(It.IsAny<List<string>>(), It.IsAny<string>()))
         .ReturnsAsync(oneWacData.Count);
    }
}

private static void PrepareData(out List<LocationWac> locationWacData, out SkuAndWac skuAndWac)
{
    locationWacData =
    [
        new LocationWac
        {
            DataPartitionKey = "sain1",
            Sku = "sku1",
            Sain = "sain1",
            WacPerUnit = 1.0m,
            LastModifiedDate = DateTime.Now,
            VariancePercent = 0.1m,
            ProductGroup = "Food"
        },
        new LocationWac
        {
            DataPartitionKey = "sain2",
            Sku = "sku2",
            Sain = "sain2",
            WacPerUnit = 1.0m,
            LastModifiedDate = DateTime.Now,
            VariancePercent = 0.1m,
            ProductGroup = "Food"
        }
    ];

    skuAndWac = new SkuAndWac
    {
        Sain = "sain1",
        Wac = 1.0m
    };
}

可成功运行的测试用例

[Fact]
public async Task RunAsync_Should_Log_BusinessException_WhenPublishingFails()
{
    //Arrange
    PrepareData(out List<LocationWac> locationWacData, out SkuAndWac skuAndWac);

    Arrange(locationWacData, true);

    //Act
    var result = await _handler.RunAsync(skuAndWac, _mockContext.Object);

    // Assert
    Assert.Equal(locationWacData.Count, result.TotalDocuments);
    Assert.Equal(0, result.TotalPublished);
    _mockErrorHandlingHelper.Verify(x => x.InsertErrorLogAsync(It.IsAny<ServiceNowErrorLog>()), Times.Once);
}

排查方向与解决方案

  1. 全局环境变量污染
    Environment.SetEnvironmentVariable是全局生效的,多个测试运行时会互相覆盖BatchSize的值。解决方案:

    • 在测试初始化时保存原有环境变量值,测试结束后恢复
    • 改用测试专用的配置注入方式,避免修改全局环境变量
  2. Mock对象未隔离
    类级别的Mock实例(如_mockLocationWacRepository)会在多个测试中共享状态,之前的Setup会累积生效。解决方案:

    • 在每个测试的[SetUp]方法中重新创建Mock实例
    • 测试结束后调用mock.Reset()清除所有Setup
  3. 测试上下文未隔离
    如果_handler、_mockContext是类级别的共享实例,前一个测试的状态会残留到下一个测试。解决方案:

    • 在[SetUp]中重新创建所有核心测试对象,确保每个测试都有干净的上下文
  4. 验证Mock调用次数
    在失败的测试中添加Mock方法的调用次数验证,确认是否被意外多次调用:

    _mockLocationWacRepository.Verify(x => x.GetCollection().FindAsync(It.IsAny<FilterDefinition<LocationWac>>(), It.IsAny<FindOptions<LocationWac, LocationWac>>(), default), Times.Once);
    

内容的提问来源于stack exchange,提问作者Juhi Shrivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:35:52