我应该如何在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()
是一个非常合理的错误;如果你没有测试行为ifisValid()
,那么你就不会知道,直到有一个神秘的生产错误,没有人认为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);
}