gpt4 book ai didi

c# - 用测试数据填充一个类

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

我正在使用反射来用测试数据填充给定的 C# 类

public object CreateObj(Type type)
{
var obj = Activator.CreateInstance(type);
var fields = type.GetFields();
foreach (var field in fields)
{
field.SetValue(obj, GetRnd(field.FieldType));
}

return obj;
}

GetRnd()函数根据字段类型设置值:

private object GetRnd(Type type)
{
if (type == typeof(int))
{
return 4;
}
else if (type == typeof(string))
{
return "text";
}
else
{
throw new Exception();
}

}

只要我向 CreateObj() 传递一个适当的类,它就可以工作。我想让它与基本类型(字符串、整数等)一起工作。到目前为止,当我传递一个简单的“int”时,我得到一个“SetType(): Cannot set a constant field”异常。

最佳答案

First of all: for a unit test it is not advised to create test objects with random values.

单元测试的目的是找出正在测试的类中的错误。当前版本和 future 版本中的错误。您的单元类不是为了查找使用正常输入时发生的错误而创建的。在代码更改后第一次运行程序时已经发现了这些错误。主要目的是找出正常运行程序时找不到的错误。

Your unit test would only give confidence in your code if it will find errors in rare cases.

通常它们被称为边缘条件:最低值、最高值、空值、最大值数、负值、空值等。

创建一个充满随机值的类需要花费大量精力来创建创建测试对象的代码,该测试对象可能会发现与您可以在一分钟内发明的任何非边缘测试对象相同的错误。在使用空数组、负数元素或偶数主数等测试代码之前,您必须运行测试一百万次。

Therefore don't put any effort in creating a unit test with random value input.

只有少数正常输入的情况,并尝试找到大量具有边缘条件的测试。

但是,创建一个工厂来创建填充随机值的任何类型的任何类可能是一个有趣的练习。

首先你应该只初始化可写的属性,因此你应该检查它们是否是。使用 System.PropertyInfo.IsWritable。

此外,扩展您的 GetRnd 函数,以便它将初始化任何原始类型使用 System.Type.IsPrimitive 和 System.Type.GetTypeCode()

如果您的可写属性之一是一个类,您的类将失败。在那种情况下,您可以递归地初始化该类。使用 System.Type.IsClass

您是否也想使用非默认构造函数初始化类?使用 System.Type.GetConstructors 查看它是否有并检查还有哪些其他构造函数可用。

数组怎么样?

额外的困难:如果你的类有一个只读属性,你可以在其中更改返回值。

class RandomObjectFactory
{
// creates an object of type T that has a default constructor
public T CreateObject<T>() where T: class, new()
{
...

此方法优于带有 Type 参数的方法,因为如果您尝试编写此方法,编译器会报错:

MyClass m = CreateObject<YourClass>();

此外,如果 MyClass 没有默认构造函数,编译器会报错。

同样,为基本类型创建一个方法是明智的:

public T CreatePrimitive<T> where T: struct, IConvertible
{
...

这可以防止以下错误:

int i = Create(typeof(Form));

创建对象的代码:

public T CreateObject<T>() where T: class, new()
{
var obj = Activator.CreateInstance<T>();
foreach (var property in typeof(T).GetProperties()
.Where(property => property.CanWrite))
{
if (property.PropertyType.IsPrimitive)
{
property.SetValue(obj, this.CreatePrimitive
(Type.GetTypeCode(property.PropertyType)));
}
else if (property.PropertyType.IsClass)
{
property.SetValue(obj, this.CreatObject...

这里我们遇到了问题:我们无法传递 property.PropertyType。

要解决这个问题:创建一个私有(private)函数 CreateObject,它接受一个 system.Type 并返回一个对象。因为这是私有(private)的,所以任何人都不能错误地使用它。

private object CreateObject(Type type)
{
var obj = Activator.CreateInstance(type);
foreach (var property in typeof(T).GetProperties()
.Where(property => property.CanWrite))
{
if (property.PropertyType.IsPrimitive)
{
property.SetValue(obj, this.CreatePrimitive
(Type.GetTypeCode(property.PropertyType)));
}
else if (property.PropertyType.IsClass)
{
property.SetValue(obj, this.CreateObject (property.PropertyType);
}
}
return obj;
}

private object CreatePrimitive(TypeCode typeCode)
{
switch (typeCode)
{
case TypeCode:Boolean:
return this.rnd.Next(2) == 0;
case TypeCode.Byte:
return (Byte)this.rnd.Next(Byte.MinValue, Byte.MaxValue);
case TypeCode.DateTime:
long ticks = (long)((DateTime.MaxValue.Ticks - DateTime.MinValue.Ticks) * rnd.NextDouble() + DateTime.MinValue.Ticks);
return new DateTime(ticks);
// etc.
}
return obj;
}

发明类似于创建结构或数组的东西。

关于c# - 用测试数据填充一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31810655/

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