gpt4 book ai didi

c# - 在单元测试中向对象断言未经验证的添加属性

转载 作者:行者123 更新时间:2023-11-30 12:47:54 27 4
gpt4 key购买 nike

我有 MSTest (VS 2012) 单元测试,我想在其中断言对象的各种属性具有我想要的值。有很多方法可以做到这一点。然而,我主要担心的是,如果将新属性添加到对象,很容易忽略更新单元测试以确保它具有我们期望的值。

我能想到的一件事是使用反射来枚举对象的公共(public)属性,然后跟踪单元测试断言了哪些属性,最后,如果没有检查到任何属性,则断言。

有没有人写过类似的东西?

有什么更好的主意吗?

更新:我应该指出,所讨论的对象类似于数据传输对象,其中有其他类/方法导致该对象中的数据被更新。很容易忽略更新这些类/方法的测试以确保我们考虑到对象的所有属性。我想要比右键单击对象、查找引用和查看代码更强大(即不能被遗忘或忽视)的东西。

例如:

public class Person {
public string FirstName;
}

public Person GetPerson() {}

[TestMethod]
public void GetPerson_ReturnsFilledInPerson()
{
var actual = target.GetPerson();
Assert.IsNotNull(actual.FirstName);
// If somebody later adds LastName to Person,
// we want this unit test to fail until the LastName is checked too.
}

谢谢,

最佳答案

你的要求不无道理。对于简单的域类到 DTO 映射,您可以使用诸如 Automapper 之类的框架。您只需告诉它域类 A 映射到 dto ADto,它就会使用约定优于配置来映射属性。该框架还附带了一种方法来测试您是否已完成所有映射。您可以调用 Mapper.AssertConfigurationIsValid(); 它将确保 Dto 中的每个属性都已映射到域类中的属性(代码中显式或具有相同属性名称的隐式).

所以基本上你正在尝试做同样的事情,这就是为什么它是一个非常有效的场景。假设您选择不使用 Automapper。我猜你的代码中没有单独的 mapper (在这种情况下你可以使用反射来测试你的映射器类/代码)。我做过类似的事情,所有 DTO 都实现了一个返回另一个 IDto 的 DeepCopy 方法。但是我们希望实际类型与调用类型相同

    [Test]
public void DeepCopyReturnsSameTypeAsOriginal()
{
var iDtoType = typeof (IDto);
var allIDtoTypes = iDtoType.Assembly.GetTypes().Where(t => iDtoType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract).ToList();

foreach (var currentIDtoType in allIDtoTypes)
{
var instanceOfDtoType = (IDto)Activator.CreateInstance(currentIDtoType);
var deepCopyType = instanceOfDtoType.DeepCopy();
Assert.AreEqual(instanceOfDtoType.GetType(), deepCopyType.GetType(),
string.Format("Deep Copy of Type '{0}' does not return the same Type. It returns '{1}'. The DeepCopy method of IDto should return the same type.",
instanceOfDtoType.GetType(), deepCopyType.GetType()));
}
}

您可以使用类似的逻辑来获取您的 person 对象。获取 person 对象的所有公共(public)属性并迭代它们,并断言您返回的具体 person 对象包含该特定属性的非空值。

尽管在这种情况下,测试只能用于非常具体的对象,您知道所有属性都必须具有非空值。以值类型为例,如果 AccountBalance 属性返回 0,则该人的余额是否为 0 或该属性是否未设置?如果此人的电子邮件属性为空,这是否意味着它未映射,或者我们只是在系统中没有此人的电子邮件。这就是为什么如果你有特定的映射器类或使用 Automapper,那么你会更具体地测试映射是否存在,而不是“这是否有值(value)”,正如我所说,这可能仍然适用于你的应用程序中的一些有限类。

另一种选择是修饰您知道不能为空且必须使用自定义属性映射的属性。例如

Public class PersonDto {
[TestNotNull]
public string FirstName { get; set}

}

然后在您的单元测试中,您可以使用反射来查找具有此属性的所有属性并确保它们不为空。但是当然你会遇到你试图在不同层次上解决的同样的问题。如果您担心人们会忘记映射重要字段,则无法保证他们会记得使用自定义属性装饰这些字段。

当然,您可能不想测试该属性是否正在映射,而只想测试该属性是否存在。在这种情况下,使用反射来获取域对象类型的所有属性的列表,并确保它们中的每一个都存在于 DTO 对象类型的属性列表中。但这并没有测试属性本身是否被映射,只是它们存在。如果您使用 Automapper 及其 AssertConfigurationIsValid() 测试,您测试的是 DTO 中的每个属性都被正确映射,而不是您域中的每个属性在 DTO 中都有关联的属性。

因此,为了回答您的问题,如果您想要测试该属性是否存在以及它是否被正确映射,您需要两个测试。一个是将域对象类型与 Dto 对象类型进行比较,并确保其中一个的属性存在于另一个中,另一个测试是为了确保 DTO 中的所有属性都被映射到某些东西(无论您是否正在进行映射在您自己的代码中或使用像 Automapper 这样的框架)。

关于c# - 在单元测试中向对象断言未经验证的添加属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15419990/

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