C# 我是否应该仅为测试目的创建新构造函数?

C# 我是否应该仅为测试目的创建新构造函数?,c#,unit-testing,testing,nunit,integration-testing,C#,Unit Testing,Testing,Nunit,Integration Testing,我有一个包含另一个对象的二维数组的类。它有一个构造函数,但在该数组中总是用零初始化。因此,其他未初始化为公平: public class FirstClass { public OtherClass[,] Others { get; set; } ... } public class OtherClass { public int Id { get; set; } } 此数组Others在运行时填充。现在,我想编写一个测试,它将在填充其他操作时测试一些操作。所以我

我有一个包含另一个对象的二维数组的类。它有一个构造函数,但在该数组中总是用零初始化。因此,
其他
未初始化为公平:

public class FirstClass
{
    public OtherClass[,] Others { get; set; }

    ...

}

public class OtherClass
{
    public int Id { get; set; }
}
此数组
Others
在运行时填充。现在,我想编写一个测试,它将在填充
其他操作时测试一些操作。所以我需要将样本数组传递给测试方法。我不想创建
OtherClass
的数组,因为我有很多这样的示例数组,我必须编写:

        OtherClass[][,] samples = new[]
        {
            new OtherClass[,]
            {
                { new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };},
                { new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };,new OtherClass() { Id = 2 };},

etc.. 
丑陋

因此,在我的
测试
项目中,我只创建了int(
Id
s)数组:

更具可读性。。。但是现在我需要为
FirstClass
创建一个构造函数,它将
int[,]
作为参数,并使用参数的ID创建其他类[,]

理论上我应该很好,因为测试看起来像:

[TestFixture]
class BoardTests
{
    [Test]
    [TestCaseSource("samples")]
    public void FirstTest(int[,] board)
    {
        FirstClass aClass = new FirstClass(board);
        //Test an operation on aClass 
    }
}
所以,我的问题是: 仅为测试创建附加构造函数是否是一种良好做法?我不会在生产代码中使用此构造函数。或者你有更好的解决方案吗

现在我需要为
FirstClass
创建一个构造函数,它将
int[,]
作为参数,并使用
Id
s从参数创建
OtherClass[,]

虽然这当然是一种选择,但如果您愿意,您当然不必这样做。保持构造函数不变的解决方案是在测试类中创建一个私有方法,将
int[,]
转换为
OtherClass[,]

private static ToOtherClass(int[,] ids) {
    var OtherClass[,] res = ...
    // Do the conversion here
    return res;
}
现在,您可以使用此方法生成不使用特殊构造函数的易于阅读的代码:

OtherClass[][,] samples = new[]
{
    ToOtherClass( new int[,]
    {
        {1,0,0,0,0,0,0},
        {0,2,0,0,0,0,0},
        {0,0,3,0,0,0,0},
        {0,0,0,4,0,0,0}
    }),
    ToOtherClass( new int[,]
    {
        {0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0},
        {1,2,3,4,5,6,7},
        {0,0,0,0,0,0,0}
    })
};

只是一个问题,不管怎样,“Others”是作为公共属性公开的,那么为什么不在测试中使用您想要的任何值来初始化它呢?您可以创建一个单独的类,在int[,]和Other[]之间进行映射(与您将在新构造函数中编写的代码相同)。这样你就把逻辑分开了。我考虑过这样的隐秘者。我只是不确定仅仅为了测试而实现附加逻辑是否好practice@AnnaLong毫无疑问,必须为测试实现这个逻辑,唯一的问题是这个逻辑将在哪里。构造函数不是只测试逻辑的好地方,因为它们保留在完成的代码中。另一方面,测试夹具是此类逻辑的完美场所,因为它们不是提供给库的用户的。最后一个问题:为什么您的
ToOtherClass
方法是静态的?我从来没有想过这一点,但是无论如何,
TestFixture
类都不需要实例化。@AnnaLong
ToOtherClass
是通常所说的“助手方法”。它属于您的测试夹具,并帮助您以更可读的格式定义测试。像这样的助手方法应该保持静态,当然,除非它们使用测试夹具的实例变量。
OtherClass[][,] samples = new[]
{
    ToOtherClass( new int[,]
    {
        {1,0,0,0,0,0,0},
        {0,2,0,0,0,0,0},
        {0,0,3,0,0,0,0},
        {0,0,0,4,0,0,0}
    }),
    ToOtherClass( new int[,]
    {
        {0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0},
        {1,2,3,4,5,6,7},
        {0,0,0,0,0,0,0}
    })
};