如何在 nsubstitute mock 上测试 set 方法

How to test set method on nsubstitute mock

现在我正坐在我的项目面前,我正在完全重写这个。我仍然无法理解如何正确编写测试。

这是我要测试的class:

namespace Snowball.Controllers
{
    public class FollowCameraController : ICameraController
    {
        private ITransform player;
        private ITransform camera;
        private IVector3Utility utility;
        private IVector3 offset;

        public FollowCameraController(ITransform player, ITransform camera, IVector3Utility utility)
        {
            this.player = player;
            this.camera = camera;
            this.utility = utility;

            offset = utility.Subtract(camera.Position, player.Position);
        }

        public void UpdateCameraPosition()
        {
            IVector3 playerPosition = player.Position;

            IVector3 newCameraPosition = utility.Add(playerPosition, offset);

            camera.Position = newCameraPosition;
        }
    }
}

这是我 运行 的测试套件,它是我目前正在尝试测试的套件中唯一的测试:

namespace FrameworkTests
{
    [TestFixture]
    public class FollowCameraControllerTest
    {
        private ITransform cameraTransformMock;
        private ITransform playerTransformMock;
        private IVector3Utility utilityMock;

        private IVector3 offset;

        private FollowCameraController sut;

        [SetUp]
        public void Init()
        {
            cameraTransformMock = Substitute.For<ITransform>();
            playerTransformMock = Substitute.For<ITransform>();
            utilityMock = Substitute.For<IVector3Utility>();

            offset = Substitute.For<IVector3>();

            utilityMock.Subtract(Arg.Any<IVector3>(), Arg.Any<IVector3>()).Returns(offset);

            sut = new FollowCameraController(cameraTransformMock, playerTransformMock, utilityMock);

            var temp = utilityMock.Received().Subtract(Arg.Any<IVector3>(), Arg.Any<IVector3>());
        }

        [Test]
        public void WhenUpdateCameraIsCalledThenCameraPositionIsUpdated()
        {
            //var playerPosition = Substitute.For<IVector3>();
            var cameraPosition = Substitute.For<IVector3>();

            var playerPosition = playerTransformMock.Position;

            utilityMock.Add(playerPosition, offset).Returns(cameraPosition);

            //var temp = cameraTransformMock.Position;
            //cameraTransformMock.Position = cameraPosition;

            sut.UpdateCameraPosition();

            var temp = playerTransformMock.Received().Position;
            temp = utilityMock.Received().Add(playerPosition, offset);
            //cameraTransformMock.Received().Position = cameraPosition;
        }
    }
}

此测试失败,并显示以下失败的测试输出:

结果信息: NSubstitute.Exceptions.ReceivedCallsException :预计会收到匹配的呼叫:

添加(IVector3Proxy, IVector3Proxy) 实际上没有收到匹配的电话。 收到 1 个不匹配的调用(不匹配的参数用 '*' 字符表示): 添加(IVector3Proxy,IVector3Proxy)

我希望有人能指出我做错了什么或者我是如何滥用 NSubstitute 的。我不知道如何测试这个方法

FollowCameraController 构造函数采用 player 然后 camera:

public FollowCameraController(ITransform player, ITransform camera, IVector3Utility utility) { ... }

但是您的测试用 camera 实例化 sut 然后 player:

sut = new FollowCameraController(cameraTransformMock, playerTransformMock, utilityMock);

我认为这是很大一部分问题。 :)

顺便说一句,UpdateCameraPosition 使用玩家位置和 IVector3Utility 实例更新相机位置,所以我将其作为测试的重点:

    [Test]
    public void WhenUpdateCameraIsCalledThenCameraPositionIsUpdated()
    {
        var newCameraPosition = Substitute.For<IVector3>();
        var playerPosition = playerTransformMock.Position;
        utilityMock.Add(playerPosition, offset).Returns(newCameraPosition);

        sut.UpdateCameraPosition();

        Assert.AreSame(cameraTransformMock.Position, newCameraPosition);
    }