使用Generics获取随机数据

时间:2008-10-07 10:06:54

标签: c# unit-testing generics

我们的一项单元测试是使用随机数据填充业务对象中的属性。

这些属性具有不同的内在类型,因此我们希望使用泛型的功能来返回您传入的类型的数据。有些内容如下:

public static T GetData<T>()

你将如何接近这个?低级别界面会起作用吗? (IConvertible)

4 个答案:

答案 0 :(得分:16)

你可以保留你所拥有的“易于使用”的GetData界面,但内部有一个Dictionary&lt; Type,object&gt;其中每个值是Func&lt; T&gt;。对于相关类型。然后GetData将具有如下实现:

public static T GetData<T>()
{
    object factory;
    if (!factories.TryGet(typeof(T), out factory))
    {
         throw new ArgumentException("No factory for type " + typeof(T).Name);
    }
    Func<T> factoryFunc = (Func<T>) factory;
    return factoryFunc();
}

然后,您将在静态初始值设定项中设置工厂字典,并为您要创建的每种类型的随机数据设置一个委托。在某些情况下,您可以使用简单的lambda表达式(例如,对于整数),在某些情况下,委托可以指向执行更多工作的方法(例如,对于字符串)。

顺便说一下,您可能希望将我的StaticRandom类用于线程安全的RNG。

答案 1 :(得分:2)

一般情况下,我会避免编写随机单元测试,因为这不是单元测试的目的。在编写单元测试时,您确实需要手动生成数据以确保覆盖类/程序中的所有路径,并且通常在测试中对此数据进行硬编码,以便重新运行测试。

所以我猜你真的在写烟雾测试,看看你的软件对大数据集的行为。在这里,我认为你应该像其他人已经建议的那样为你的每个业务对象类型实现一个特定的生成器 - 以确保数据与你在生产中的期望相似(例如,如果ID是顺序的,那么生成顺序和不随机)。

答案 2 :(得分:1)

这取决于您要随机化的数据,因为您要使用的方式算法完全不同,具体取决于类型。

例如:

// Random int
Random r = new Random();
return r.Next();

// Random Guid
return Guid.NewGuid();

...

所以这显然使得泛型在用户端的使用变得很好,但是它对你编写类的方式没有任何价值。您可以使用switch子句或字典(如Jon Skeet建议的那样):

switch(typeof(T))
{
    case System.Int32:
        Random r = new Random();
        return (T)r.Next();
    case System.Guid:
        return (T)Guid.NewGuid();
    ...

然后你可以按预期使用该课程:

RandomGenerator.GetData<Guid>();
...

答案 3 :(得分:0)

我会使用AutoPoco生成测试所需的数据。