您可以通过使用工厂模式或构建器模式来创建对象来帮助减轻这些负担。
构建器模式的一个简化示例是:
public class Foo
{
public string Prop1 { get; private set; }
public Foo(string prop1)
{
this.Prop1 = prop1;
}
}
[TestClass]
public class FooTests
{
[TestMethod]
public void SomeTestThatRequiresAFoo()
{
Foo f = new Foo("a");
// testy stuff
}
[TestMethod]
public void SomeTestThatRequiresAFooUtilizingBuilderPattern()
{
Foo f = new FooBuilder().Build();
}
[TestMethod]
public void SomeTestThatRequiresAFooUtilizingBuilderPatternOverrideDefaultValue()
{
Foo f = new FooBuilder()
.WithProp1("different than default")
.Build();
}
}
internal class FooBuilder
{
public string Prop1 { get; private set; }
// default constructor, provide default values to Foo object
public FooBuilder()
{
this.Prop1 = "test";
}
// Sets the "Prop1" value and returns this, done this way to create a "Fluent API"
public FooBuilder WithProp1(string prop1)
{
this.Prop1 = prop1;
return this;
}
// Builds the Foo object by utilizing the properties created as BuilderConstruction and/or the "With[PropName]" methods.
public Foo Build()
{
return new Foo(
this.Prop1
);
}
}
这样,如果/当您的 Foo 对象更改时,更新单元测试以将更改考虑在内会更容易一些。
考虑:
public class Foo
{
public string Prop1 { get; private set; }
public string Prop2 { get; private set; }
public Foo(string prop1, string prop2)
{
this.Prop1 = prop1;
this.Prop2 = prop2
}
}
使用此实现,您的单元测试将中断,但更新您的构建器比更新每个单元测试更容易依赖于 Foo 的正确构造
internal class FooBuilder
{
public string Prop1 { get; private set; }
public string Prop2 { get; private set; }
// default constructor, provide default values to Foo object
public FooBuilder()
{
this.Prop1 = "test";
this.Prop2 = "another value";
}
// Sets the "Prop1" value and returns this, done this way to create a "Fluent API"
public FooBuilder WithProp1(string prop1)
{
this.Prop1 = prop1;
return this;
}
// Similar to the "WithProp1"
public FooBuilder WithProp2(string prop2)
{
this.Prop2 = prop2;
return this;
}
// Builds the Foo object by utilizing the properties created as BuilderConstruction and/or the "With[PropName]" methods.
public Foo Build()
{
return new Foo(
this.Prop1,
this.Prop2
);
}
}
使用 Foo 和 FooBuilder 的这种新实现,唯一会破坏的单元测试是手动创建 Foo 的单元测试,使用单元测试的 FooBuilder 仍然可以正常工作。
这是一个简化的示例,但想象一下,如果您有 20-30 个单元测试依赖于 Foo 对象的构造。无需更新那些 20-30 个单元测试,您只需更新您的构建器以正确构造 Foo 对象。
在您在构造函数中对 null 进行单元测试的示例中,您可以使用构建器模式编写单元测试,如下所示:
[TestMethod]
public void TestWithNullInFirstParam()
{
Foo f = new FooBuilder()
.WithProp1(null)
.Build()
// in this case "f" will have Prop1 = null, prop2 = "another value"
}