From 559bd1ab6e9beafcf2b5917f05a5f17931125466 Mon Sep 17 00:00:00 2001 From: Philip Fyvie Date: Thu, 29 Sep 2016 18:47:50 +0900 Subject: [PATCH] Added test for tile manager event deregistration to resolve Issue #8. --- Tests/Management/TileChangeManagerTests.cs | 81 +++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/Tests/Management/TileChangeManagerTests.cs b/Tests/Management/TileChangeManagerTests.cs index 043fec9..8a34646 100644 --- a/Tests/Management/TileChangeManagerTests.cs +++ b/Tests/Management/TileChangeManagerTests.cs @@ -161,8 +161,85 @@ public void TileChangeEvents() [Test] public void TileChangeEntityDestroyedDeregisterEvents() { - // TODO: Issue 8 (https://github.com/Wizcorp/TileSystem/issues/8) - Assert.Fail(); + // A tile manager should deregister an entity when it raises a Destroy event. + + TileChangeManager manager = new TileChangeManager(); + + // Our mock entity should implement both IEntity (for raising Destroy) and IChangeTile (for performing movement) + Mock mockEntity = new Mock(); + Mock mockMovable = mockEntity.As(); + + // Our mock creator is used only to create our mocked entity. + Mock mockCreator = new Mock(); + + // Two mocked tiles to move between + Mock mockTileFrom = new Mock(); + Mock mockTileTo = new Mock(); + + // Our first mock solver will be checked to ensure it's receiving the events. + Mock mockSolverOne = new Mock(); + + // These tile change args classes will permit the solver to be invoked upon event propogation. + TileChangedArgs tileStartArgs = new TileChangedArgs(mockTileFrom.Object, mockTileTo.Object, TileChangeType.Start); + TileChangedArgs tileChangeArgs = new TileChangedArgs(mockTileFrom.Object, mockTileTo.Object, TileChangeType.Change); + TileChangedArgs tileFinishArgs = new TileChangedArgs(mockTileFrom.Object, mockTileTo.Object, TileChangeType.Finish); + + // Our mocked movable entity should emit tile change start, changing, and finished events. + mockMovable.Setup(movable => movable.StartChangeTile(mockTileFrom.Object, mockTileTo.Object)) + .Raises(m => m.ChangeStarted += null, mockMovable.Object, tileStartArgs); + + mockMovable.Setup(movable => movable.ChangeTile(mockTileFrom.Object, mockTileTo.Object)) + .Raises(m => m.Changing += null, mockMovable.Object, tileChangeArgs); + + mockMovable.Setup(movable => movable.FinishChangeTile(mockTileFrom.Object, mockTileTo.Object)) + .Raises(m => m.ChangeFinished += null, mockMovable.Object, tileFinishArgs); + + // Register the entity creator with the tile manager. + manager.RegisterEntityCreator(mockCreator.Object); + + // Our first solver must be added before it will receive events. + manager.Add(mockSolverOne.Object); + + // Raise an entity creation event to register that entity for tile change events. + mockCreator.Raise(creator => creator.EntityCreated += null, mockCreator.Object, new EntityCreatedArgs(mockTileFrom.Object, mockEntity.Object)); + + // Move the entity. + mockMovable.Object.StartChangeTile(mockTileFrom.Object, mockTileTo.Object); + mockMovable.Object.ChangeTile(mockTileFrom.Object, mockTileTo.Object); + mockMovable.Object.FinishChangeTile(mockTileFrom.Object, mockTileTo.Object); + + // The entity's movement should have invoked each corresponding state transition method once. + // Solver One has received one set of events. + + // Add a second solver, for differential comparison. + Mock mockSolverTwo = new Mock(); + manager.Add(mockSolverTwo.Object); + + // Move the entity a second time. + mockMovable.Object.StartChangeTile(mockTileFrom.Object, mockTileTo.Object); + mockMovable.Object.ChangeTile(mockTileFrom.Object, mockTileTo.Object); + mockMovable.Object.FinishChangeTile(mockTileFrom.Object, mockTileTo.Object); + + // The two solvers should have again incremented their movement method invocation count once each. + // Solver One has received two sets of events, Solver Two has received one set of events. + + // Raise a Destroy event from the entity (via its IEntity mock), which should trigger deregistration. + mockEntity.Raise(movable => movable.Destroyed += null, new EntityDestroyedArgs(mockEntity.Object)); + + // Move the entity a third time. + mockMovable.Object.StartChangeTile(mockTileFrom.Object, mockTileTo.Object); + mockMovable.Object.ChangeTile(mockTileFrom.Object, mockTileTo.Object); + mockMovable.Object.FinishChangeTile(mockTileFrom.Object, mockTileTo.Object); + + // Because the entity was deregistered, neither solver incremented its movement method invocation count. + // Solver One has received two sets of events, Solver Two has received one set of events. + // Should deregistration be faulty, we'd expect the invocation counts to stand at 3 and 2, repsectively. + mockSolverOne.Verify(solver => solver.Solve(mockEntity.Object, tileStartArgs), Times.Exactly(2)); + mockSolverOne.Verify(solver => solver.Solve(mockEntity.Object, tileChangeArgs), Times.Exactly(2)); + mockSolverOne.Verify(solver => solver.Solve(mockEntity.Object, tileFinishArgs), Times.Exactly(2)); + mockSolverTwo.Verify(solver => solver.Solve(mockEntity.Object, tileStartArgs), Times.Exactly(1)); + mockSolverTwo.Verify(solver => solver.Solve(mockEntity.Object, tileChangeArgs), Times.Exactly(1)); + mockSolverTwo.Verify(solver => solver.Solve(mockEntity.Object, tileFinishArgs), Times.Exactly(1)); } [Test]