如何确保域实体的方法先于其他方法被调用?

时间:2018-08-11 17:25:00

标签: c# unit-testing .net-core

我想编写一个测试来确保在存储库方法之前调用了我的域实体的方法,因此我可以保证信息在保留之前已被更改。

因此在我的示例域服务实现中,我颠倒了调用的顺序,所以我可以看到测试失败。

using NSubstitute;
using Xunit;

namespace MyProject
{
    public interface IMyService
    {
        void MyServiceMethod(MyEntity entity);
    }

    public interface IMyRepository
    {
        void Persist(MyEntity entity);
    }

    public class MyEntity
    {
        public string MyProp { get; private set; }

        public void ChangeMyProp(string newValue)
        {
            MyProp = newValue;
        }
    }

    public class MyService : IMyService
    {
        private readonly IMyRepository _myRepository;
        public MyService(IMyRepository repository)
        {
            _myRepository = repository;
        }

        public void MyServiceMethod(MyEntity entity)
        {
            _myRepository.Persist(entity); // this is a wrong fake implementation that should me caught on test
            entity.ChangeMyProp("I am changing you");
        }
    }

    public class MyServiceTest
    {
        [Fact]
        public void MyServiceMethod_Should_ChangeProp_Before_Persists()
        {
            var repository = Substitute.For<IMyRepository>();
            var service = new MyService(repository);
            var myEntity = new MyEntity();

            service.MyServiceMethod(myEntity);

            Received.InOrder(() =>
            {
                myEntity.ChangeMyProp("I am changing you");
                repository.Persist(myEntity);
            });
        }
    }
}

问题是该测试通过了。我唯一能想到的就是为我的MyEntity编写一个接口或将该方法设为虚拟,因此nsubstitute可以处理该接口,但这听起来对我不利,因为这是我的域实体,域外的任何人都不应实施或重写此逻辑。

有什么方法可以测试此电话订单?

PS:如果您只知道Moq或其他Mock库如何做到这一点,那不是问题。这也会对我有帮助。我可以更改它。

修改

我也尝试了以下代码,但没有用。这也过去了。

repository.Received().Persist(Arg.Is<MyEntity>(e => e.MyProp == "I am changing you"));

编辑2

我在github上发现了一个相关问题,该问题可以帮助我解决问题,并发布了答案。尽管我不喜欢这种解决方案,因为它对我来说不是很干净,但是可以,这是我目前拥有的全部。

2 个答案:

答案 0 :(得分:0)

您可以只验证Persist方法接收的内容。如果接收到的实体具有更改的值,则说明订单正确。 验证对无法模拟的对象的方法调用总是很困难,并且通常指向设计问题。

答案 1 :(得分:0)

我找到了解决方法here

    [Fact]
    public void MyServiceMethod_Should_ChangeProp_Before_Persists()
    {
        var repository = Substitute.For<IMyRepository>();
        var service = new MyService(repository);
        var myEntity = new MyEntity();
        var namePersisted = string.Empty;

        repository.Persist(Arg.Do<MyEntity>(e => namePersisted = e.MyProp));
        service.MyServiceMethod(myEntity);

        Assert.Equal(myEntity.MyProp, namePersisted);
    }