单元测试批量执行失败,单独运行正常的问题排查求助
单元测试异常问题
运行整个测试类时,某测试用例会失败,但单独运行该测试时却正常(已在代码中标记)。调试时通过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
相关产品推荐
相关产品推荐

