【发布时间】: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<Picture>(Expression<Func<Picture, bool>>) 应该返回数据库中 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