我应该如何在C#中对多个必填字段进行单元测试?

我应该如何在C#中对多个必填字段进行单元测试?,c#,unit-testing,C#,Unit Testing,想象一下这个简单的场景:我有一个名为MyModel的类: public class MyModel { public string Prop01 { get; set; } public string Prop02 { get; set; } public string Prop03 { get; set; } public bool IsValid() { if (String.IsNullOrEmpty(Prop01) || Stri

想象一下这个简单的场景:我有一个名为
MyModel
的类:

public class MyModel
{
    public string Prop01 { get; set; }
    public string Prop02 { get; set; }
    public string Prop03 { get; set; }

    public bool IsValid()
    {
        if (String.IsNullOrEmpty(Prop01) || String.IsNullOrEmpty(Prop02) || String.IsNullOrEmpty(Prop03))
            return false;

        return true;
    }
}
如您所见,如果
MyModel
上的任何属性为null或空,
IsValid()
方法将返回
false
,换句话说,所有字段都是“必需的”

我编写了一些单元测试来测试
IsValid()
方法:

[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
    var myModel = new MyModel();
    Assert.AreEqual(myModel.IsValid(), false);
}

[TestMethod]
public void MyModel_Invalid_When_Prop02_Is_Null()
{
    var myModel = new MyModel();
    Assert.AreEqual(myModel.IsValid(), false);
}

[TestMethod]
public void MyModel_Invalid_When_Prop03_Is_Null()
{
    var myModel = new MyModel();
    Assert.AreEqual(myModel.IsValid(), false);
}
当然,所有这些测试都会通过,但我对此不太满意。让我们想象一下,我是一个开发人员,当Prop01测试为Null时,看到
MyModel\u无效(这是另一个开发人员编写的)。我希望只要给
myModel
Prop01
赋值,测试就会失败。但这当然不会发生,所以我将测试更改为如下:

[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
    var myModel = new MyModel();
    myModel.Prop02 = "Some value";
    myModel.Prop03 = "Some value";

    Assert.AreEqual(myModel.IsValid(), false);
}

[TestMethod]
public void MyModel_Invalid_When_Prop02_Is_Null()
{
    var myModel = new MyModel();
    myModel.Prop01 = "Some value";
    myModel.Prop03 = "Some value";

    Assert.AreEqual(myModel.IsValid(), false);
}

[TestMethod]
public void MyModel_Invalid_When_Prop03_Is_Null()
{
    var myModel = new MyModel();
    myModel.Prop01 = "Some value";
    myModel.Prop02 = "Some value";

    Assert.AreEqual(myModel.IsValid(), false);
}
现在测试是真正的测试每个属性是否已填充,但是如果我在
MyModel
中添加一个
Prop04
,这也是必填字段,我需要再次更改所有的单元测试,所以我认为这不是一个好主意


因此,我的问题是:我如何才能单元测试多个必需的属性,以确保测试通过或失败,因为我正在测试特定的属性?或者,我应该测试这些场景吗?

而不是从一个空的、无效的模型开始,您可以从一个有效的开始,然后使其无效。这将确保您只需要在一个地方修改测试,这很好,因为您的实际需求发生了变化

另一个优点是,您的测试变得更加明确,因为安装程序明确地使您的模型无效:

[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
    var myModel = getValidModel();
    myModel.Prop01 = null;    
    Assert.AreEqual(myModel.IsValid(), false);
}

[TestMethod]
public void MyModel_Invalid_When_Prop02_Is_Null()
{
    var myModel = getValidModel();
    myModel.Prop02 = null;

    Assert.AreEqual(myModel.IsValid(), false);
}

[TestMethod]
public void MyModel_Invalid_When_Prop03_Is_Null()
{
    var myModel = getValidModel();
    myModel.Prop03 = null;

    Assert.AreEqual(myModel.IsValid(), false);
}

MyModel getValidModel() => 
    new MyModel
    {
        Prop01 = "Some value",
        Prop02 = "Some value",
        Prop03 = "Some value",
    };
如果模型初始化变得更复杂,则可以使用生成器模式。
我写了一篇关于这一点的博客文章,这可能会有所帮助:

在我看来,如果
isValid()
足够重要,足以成为一种方法,那么它的行为就应该得到测试

在某些方面,它的简单逻辑可能会让你觉得它不值得所有的工作。好吧,我明白了,但相反的论点是,如果有人添加了另一个必填字段,那么未能更新
isValid()
是一个非常合理的错误;如果你没有测试行为if
isValid()
,那么你就不会知道,直到有一个神秘的生产错误,没有人认为Prop04是空的,因为嘿,
isValid()
返回true

所以是的,我会测试它;但是,是的,你可以让这更容易。您可以在测试类中创建一个helper函数,该函数生成
MyModel
的虚拟实例,并填充所有字段。那么你的测试方法就像

(请原谅任何代码错误;我不是在编译,但我想你会明白我的意思…)

当然,您还有另一个测试方法,它不会将任何属性设置为Null,并断言
IsValid()
应该返回true


因此,现在您添加了一个新属性,您添加了一个新的测试方法(这是您期望必须执行的)。更新辅助对象以填充新属性;无论如何,您都需要它来支持“
IsValid()
is true”案例。因此,其他现有的测试方法都不需要更新。

非常好!谢谢你的回答!很乐意帮忙*如果答案对你有帮助,请投票/接受
[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
    var myModel = getMyModelInstance();
    myModel.Prop01 = Null;

    Assert.AreEqual(myModel.IsValid(), false);
}