【问题标题】:Moq: Setting Up Method That Compares Guids Inside A Lambda Expression FailsMoq:设置比较 Lambda 表达式中的 Guid 的方法失败
【发布时间】:2014-05-13 22:40:01
【问题描述】:

这似乎是一项非常简单的任务,但我发现在起订量中很难完成。我有一个存储库,它调用一个工作单元来从数据库中查询一张随机图片。这个查询有一个约束;数据库中的随机图片不能与当前显示的图片相同。我正在为存储库构建一个 NUnit 测试,我想像这样模拟工作单元:

[TestFixture]
public class When_the_next_random_picture_for_TopSlidePicture_show_has_been_requested
{
    private Guid _currentPictureID;
    private Picture _randomPicture;
    private Mock<IUnitOfWork<Guid>> _unitOfWorkMock;

    [SetUp]
    public void Context()
    {
        _currentPictureID = Guid.NewGuid();
        _randomPicture = new Picture { ID = Guid.NewGuid() };
        _unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
        //TODO:  Find out how to setup and verify expression when mocking method with equality comparison in a lambda expression.
        _unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(pic => pic.ID != _currentPictureID))
            .Returns(_randomPicture);
    }

    [Test]
    public void The_PictureRepository_can_query_next_random_picture()
    {
        //Arrange
        var picRepo = new PictureRepository(_unitOfWorkMock.Object);

        //Act
        var randomPicture = picRepo.GetNextRandomPicture(_currentPictureID);

        //Assert
        _unitOfWorkMock.Verify(uow => 
            uow.GetRandom<Picture>(pic => pic.ID != _currentPictureID)
            , Times.Once());

        Assert.AreEqual(_randomPicture, randomPicture);
    }
}

在上面的代码中,UnitOfWork 中的GetRandom&lt;Picture&gt;(Expression&lt;Func&lt;Picture, bool&gt;&gt;) 应该返回数据库中 Guid ID 不等于当前图片 ID 的任何图片。但是,无论 _randomPicture 的值如何,从 _unitOfWorkMock 调用的 Setup() 方法都会返回 null。经过大量研究,我发现了以下过程:

_unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
_unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(It.IsAny<Expression<Func<Picture, bool>>>()))
    .Returns(_randomPicture); 

var randomPicture = picRepo.GetNextRandomPicture(_currentPictureID);

//Assert
_unitOfWorkMock.Verify(uow => 
    uow.GetRandom<Picture>(It.IsAny<Expression<Func<Picture, bool>>>())
    , Times.Once());

这允许测试通过。但是,我没有测试从db返回的图片是否与传入的当前图片ID相同的Guid ID;这是构建测试的关键原则!!!

我喜欢 Moq 框架,并且比所有其他测试工具更喜欢它,但就单元测试平台而言,这似乎是对完整性的巨大破坏。请有人告诉我我看不清楚的地方,并告诉我一个简单易行的方法来完成这个看似简单的任务!

感谢

更新

感谢@StriplingWarrior,我能够解决问题!他的布尔代数是错误的,但他的回答是正确的 ;-) 我发现对上述代码的这些修改是有效的:

        _unitOfWorkMock = new Mock<IUnitOfWork<Guid>>();
        _unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))))
            .Returns(_randomPicture);

    private bool TestIdMatchExpression(Expression<Func<Picture, bool>> expr)
    {
        var func = expr.Compile();

        Assert.IsFalse(func(new Picture { ID = _referencePictureID }));

        return true;
    }

         //Assert
         _unitOfWorkMock.Verify(uow =>
             uow.GetRandom<Picture>(It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e)))
             , Times.Once());

再次感谢@StriplingWarrior!

【问题讨论】:

    标签: c# unit-testing lambda nunit moq


    【解决方案1】:

    您应该能够使用It.Is&lt;&gt;() 的特殊重载来测试表达式:

    It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))
    

    从那里你只需要找出检查传入表达式的最佳方法。最简单的方法可能是测试行为:表达式应该匹配具有相同 guid 的图片,并拒绝带有不同的。

    bool TestIdMatchExpression(Expression<Func<Picture, bool>> expr)
    {
        var func = expr.Compile();
        Assert.IsTrue(func(new Picture{ID = _currentPictureID}));
        Assert.IsFalse(func(new Picture{ID = Guid.NewGuid()}));
    }
    

    【讨论】:

      【解决方案2】:

      请记住,当您对方法进行单元测试时,您必须隔离该测试,模拟每个外部依赖项,包括您案例中的数据库,针对外部依赖项的不同条件对该方法进行测试

       Picture randomPictureExpected = new Picture{ ID=Guid.NewGuid()}; 
         _unitOfWorkMock.Setup(uow => uow.GetRandom<Picture>(pic=>pic.ID!=_currentPictureID))
                         .Returns(randomPictureExpected);   
      

      你的断言会是这样的

      var randomPictureActual = picRepo.GetNextRandomPicture(_currentPictureID);
      
        Assert.AreEqual (randomPictureExpected.ID, randomPictureActual.ID);
      

      【讨论】:

        猜你喜欢
        • 2012-09-11
        • 2012-05-22
        • 2017-03-29
        • 2014-10-11
        • 2020-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-02
        相关资源
        最近更新 更多