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

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

单元测试异常问题

运行整个测试类时,某测试用例会失败,但单独运行该测试时却正常(已在代码中标记)。调试时通过Session.Query<IIslandViewModel>().Count()确认:调用Session.Fire()时仅存在一个IIslandViewModel对象,且每个测试的Teardown都会清理该对象,两种执行方式下此情况无差异。测试失败的直接原因是规则被错误触发。

测试代码

[TestFixture]
public class _2ConnectionsRule1Tests : TestBase
{
    public _2ConnectionsRule1Tests()
    {
        Setup.Rule<_2ConnectionsRule1>();
    }

    [Test]
    public void _2ConnectionsRule1_WhenTwoValidNeighbors_ShouldTriggerRule()
    {
        // arrange
        var testIsland = CreateTestIslandMock(TestIslandEnum.TestIsland, 2);

        // valid neighbors
        var leftIsland = CreateTestIslandMock(TestIslandEnum.LeftIsland, 2);
        var rightIsland = CreateTestIslandMock(TestIslandEnum.RightIsland, 2);

        testIsland.Setup(mock => mock.GetAllVisibleNeighbors())
            .Returns([leftIsland.Object, rightIsland.Object]);

        // act
        Session.Insert(testIsland.Object);
        Session.Fire();

        // assert
        Verify(x => x.Rule().Fired(Times.Once));
        ConnectionManagerMock.Verify(mock => mock.AddConnection(testIsland.Object, leftIsland.Object, true), Moq.Times.Once);
        ConnectionManagerMock.Verify(mock => mock.AddConnection(testIsland.Object, rightIsland.Object, true), Moq.Times.Once);
    }

    // 运行整个测试类时失败,单独运行正常
    [Test]
    public void _2ConnectionsRule1_WhenTwoValidNeighborsAndAdditionalNeighbors_ShouldNotTriggerRule()
    {
        // arrange
        var testIsland = CreateTestIslandMock(TestIslandEnum.TestIsland, 2);

        // valid neighbors
        var leftIsland = CreateTestIslandMock(TestIslandEnum.LeftIsland, 2);
        var rightIsland = CreateTestIslandMock(TestIslandEnum.RightIsland, 2);

        // invalid neighbor
        var upIsland = CreateTestIslandMock(TestIslandEnum.UpIsland, 4);

        testIsland.Setup(mock => mock.GetAllVisibleNeighbors())
            .Returns([leftIsland.Object, rightIsland.Object, upIsland.Object]);

        // act
        Session.Insert(testIsland.Object);
        Session.Fire();

        // assert
        Verify(x => x.Rule().Fired(Times.Never));
    }

    [Test]
    public void _2ConnectionsRule1_WhenMoreThanTwoValidNeighbors_ShouldNotTriggerRule()
    {
        // similar approach here
    }

    [Test]
    public void _2ConnectionsRule1_WhenLessThanTwoValidNeighbors_ShouldNotTriggerRule()
    {
        // similar approach here
    }

    [Test]
    public void _2ConnectionsRule1_WhenNoValidNeighbors_ShouldNotTriggerRule()
    {
        // similar approach here
    }
}

TestBase代码

public abstract class TestBase : RulesTestFixture
{
    protected Mock<IConnectionManagerViewModel> ConnectionManagerMock;

    [OneTimeSetUp]
    public void OneTimeSetup()
    {
        ConnectionManagerMock = new Mock<IConnectionManagerViewModel>(MockBehavior.Strict);
        ConnectionManagerMock.SetupProperty(mock => mock.AreRulesBeingApplied, true);
        ConnectionManagerMock.SetupProperty(mock => mock.RuleMessage, string.Empty);
        ConnectionManagerMock.Setup(mock => mock.AddConnection(It.IsAny<IIslandViewModel>(), It.IsAny<IIslandViewModel>(), true));
        Session.Insert(ConnectionManagerMock.Object);
    }

    [SetUp]
    public void SetUp()
    {

    }

    [TearDown]
    public void TearDown()
    {
        Session.RetractAll(Session.Query<IIslandViewModel>());
    }

    protected Mock<IIslandViewModel> CreateTestIslandMock(TestIslandEnum islandEnum, int maxConnections, bool maxConnectionsReached = false)
    {
        return islandEnum switch
        {
            TestIslandEnum.TestIsland => CreateIslandMock(1, 1, maxConnections, maxConnectionsReached),
            TestIslandEnum.LeftIsland => CreateIslandMock(0, 1, maxConnections, maxConnectionsReached),
            TestIslandEnum.RightIsland => CreateIslandMock(2, 1, maxConnections, maxConnectionsReached),
            TestIslandEnum.UpIsland => CreateIslandMock(1, 0, maxConnections, maxConnectionsReached),
            TestIslandEnum.DownIsland => CreateIslandMock(1, 2, maxConnections, maxConnectionsReached),
            _ => throw new ArgumentOutOfRangeException(nameof(islandEnum), islandEnum, null)
        };
    }

    protected Mock<IHashiPoint> CreateHashiPointMock(int x, int y)
    {
        var hashPointMock = new Mock<IHashiPoint>(MockBehavior.Strict);
        hashPointMock.Setup(mock => mock.X).Returns(x);
        hashPointMock.Setup(mock => mock.Y).Returns(y);
        return hashPointMock;
    }

    private Mock<IIslandViewModel> CreateIslandMock(int x, int y, int maxConnections, bool maxConnectionsReached)
    {
        var islandMock = new Mock<IIslandViewModel>(MockBehavior.Strict);
        islandMock.Setup(mock => mock.Coordinates).Returns(CreateHashiPointMock(x, y).Object);
        islandMock.Setup(mock => mock.MaxConnections).Returns(maxConnections);
        islandMock.Setup(mock => mock.MaxConnectionsReached).Returns(maxConnectionsReached || maxConnections == 0);
        islandMock.Setup(mock => mock.GetAllVisibleNeighbors()).Returns(new List<IIslandViewModel>());
        islandMock.Setup(mock => mock.AllConnections).Returns(new ObservableCollection<IHashiPoint>());
        islandMock.Setup(mock => mock.RefreshIslandColor());
        return islandMock;
    }
}

规则代码

public class _2ConnectionsRule1 : BaseRule
{
    protected override string RuleMessage => TranslationSource.Instance[nameof(_2ConnectionsRule1)]!;

    /// <inheritdoc />
    public override void Define()
    {
        IIslandViewModel island = null!;
        List<IIslandViewModel> allNeighbors = null!;
        List<IIslandViewModel> validNeighbors = null!;
        List<IIslandViewModel> invalidNeighbors = null!;
        IConnectionManagerViewModel connectionManager = null!;

        When()
            .Match(() => island, x => x.AllConnections.Count == 0 && x.MaxConnections == 2)
            .Query(() => connectionManager, q => q.Match<IConnectionManagerViewModel>())
            .Let(() => allNeighbors, () => island.GetAllVisibleNeighbors())
            .Let(() => invalidNeighbors, () => allNeighbors.Where(x => !x.MaxConnectionsReached && x.MaxConnections != 2).ToList())
            .Let(() => validNeighbors, () => allNeighbors.Where(x => x.MaxConnections == 2 && !x.MaxConnectionsReached).ToList())
            .Having(() => invalidNeighbors.Count == 0 && validNeighbors.Count == 2);

        Then()
            .Do(ctx => AddConnections(island, validNeighbors, connectionManager));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:25:06