背景
我有一个使用NHibernate将对象持久化到数据库的类。当您为没有设置ID的对象调用MergeEntity
时,NHibernate会在返回时使用ID填充该对象。为了确保我总是使用NHibernate使用的相同对象,我将更新后的对象从我的" Save
"功能
问题
我正在尝试使用Moq来模拟相同的行为,这通常非常直观且易于使用;但是,我在验证使用正确的参数调用Save()
时遇到了一些麻烦。我想验证传入的对象的ID是否为零,然后由Save
函数正确设置。不幸的是,当我修改Moq.Returns()
函数中的ID时,Moq.Verify
函数使用修改后的值而不是传入的ID值。
为了说明,这是一个非常基本的类(我重写了ToString()函数,因此我的测试输出将显示调用模拟的Save()时使用的ID:
public class Class1
{
private readonly IPersistence _persistence;
/// <summary>Initializes a new instance of the <see cref="T:System.Object" /> class.</summary>
public Class1(IPersistence persistence)
{
_persistence = persistence;
}
public int Id { get; set; }
public void Save()
{
_persistence.Save(this);
}
public override string ToString()
{
return Id.ToString();
}
}
这是界面(非常直接):
public interface IPersistence
{
Class1 Save(Class1 one);
}
以下是我认为应该通过的测试:
[TestFixture]
public class Class1Tests
{
[Test]
public void Save_NewObjects_IdsUpdated()
{
var mock = new Mock<IPersistence>();
mock.Setup(x => x.Save(It.IsAny<Class1>()))
.Returns((Class1 c) =>
{
// If it is a new object, then update the ID
if (c.Id == 0) c.Id = 1;
return c;
});
// Verify that the IDs are updated for new objects when saved
var one = new Class1(mock.Object);
Assert.AreEqual(0, one.Id);
one.Save();
mock.Verify(x => x.Save(It.Is<Class1>(o => o.Id == 0)));
}
}
不幸的是,它没有说它从未使用符合该条件的参数调用。在模拟上对Save
进行的唯一调用是使用ID为1的对象。我已经验证了对象在进入返回函数时的ID为0。如果我更新Returns()
函数中的值,我是否无法区分传入模拟的内容与更新的内容?
答案 0 :(得分:1)
您可以将其切换为验证使用正确的对象完成了保存。然后声称Id已按预期更改。
[Test]
public void Save_NewObjects_IdsUpdated() {
//Arrange
var expectedOriginalId = 0;
var expectedUpdatedId = 1;
var mock = new Mock<IPersistence>();
mock.Setup(x => x.Save(It.Is<Class1>(o => o.Id == expectedOriginalId)))
.Returns((Class1 c) => {
// If it is a new object, then update the ID
if (c.Id == 0) c.Id = expectedUpdatedId;
return c;
}).Verifiable();
var sut = new Class1(mock.Object);
var actualOriginalId = sut.Id;
//Act
sut.Save();
//Assert
//verify id was 0 before calling method under test
Assert.AreEqual(expectedOriginalId, actualOriginalId);
//verify Save called with correct argument
//ie: an object that matched the predicate in setup
mock.Verify();
// Verify that the IDs are updated for new objects when saved
Assert.AreEqual(expectedUpdatedId, sut.Id);
}
通过在设置上应用过滤器并使其可验证,然后确认该方法实际上是使用ID为零的对象调用的。
我已经测试了这个并且它通过了。要确认这是否按预期工作,您可以在执行操作之前从预期的起始ID更改sut的ID。验证将失败,因为它与谓词不匹配。
这应该满足你想要达到的目标。