在Lambda表达式中设置比较Guids的方法失败

本文关键字:Guids 方法 失败 比较 设置 Lambda 表达式 | 更新日期: 2023-09-27 18:03:07

这似乎是一个非常简单的任务,但我发现在Moq中很难完成。我有一个存储库,它调用一个工作单元从数据库中查询随机图片。这个查询有一个约束;数据库中的随机图片不能等于当前显示的图片。我正在为存储库构建一个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<Picture>(Expression<Func<Picture, bool>>)应该返回数据库中Guid ID不等于当前图片ID的任何图片。然而,从_unitOfWorkMock调用的Setup()方法返回null,不管_randomPicture的值是多少。经过一番研究,我找到了以下步骤:

_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());

这允许测试通过。但是,我没有测试从数据库返回的图片是否与传入的当前图片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!

在Lambda表达式中设置比较Guids的方法失败

您应该能够使用It.Is<>()的特殊过载来测试表达式:

It.Is<Expression<Func<Picture, bool>>>(e => TestIdMatchExpression(e))
从那里你只需要找出最好的方法来检查传递进来的表达式。最简单的方法可能是测试行为:表达式应该匹配具有相同guid的图片,并拒绝具有不同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()}));
}

记住,当你对一个方法进行单元测试时,你必须隔离该测试,模拟每个外部依赖,包括数据库,在不同的外部依赖条件下对该方法进行测试

 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);