gpt4 book ai didi

c# - Moq 验证使用返回中修改的对象,而不是实际传入的对象

转载 作者:行者123 更新时间:2023-11-30 12:41:16 25 4
gpt4 key购买 nike

背景

我有一个使用 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)));
}
}

不幸的是,它没有说明从未使用符合该标准的参数调用它。在 mock 上对 Save 的唯一调用是使用 ID 为 1 的对象。我已验证这些对象在进入 Returns 函数时 ID 为 0。如果我更新我的 Returns() 函数中的值,我是否无法区分传递到模拟中的内容与这些对象更新后的内容?

最佳答案

您可以切换它以验证保存是使用正确的对象完成的。然后断言 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。验证将失败,因为它与谓词不匹配。

这应该能满足您要实现的目标。

关于c# - Moq 验证使用返回中修改的对象,而不是实际传入的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38062321/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com