Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该如何在单元测试中检查工厂创建的对象图_C#_Unit Testing_Tdd - Fatal编程技术网

C# 我应该如何在单元测试中检查工厂创建的对象图

C# 我应该如何在单元测试中检查工厂创建的对象图,c#,unit-testing,tdd,C#,Unit Testing,Tdd,我有一些类似于以下的代码: public interface IMyClass { MyEnum Value { get; } IMyItemCollection Items { get; } } public class MyConcreteClassFactory : MyClassFactoryBase { public override IMyClass Create(MyEnum value) { var itemBuilder = n

我有一些类似于以下的代码:

public interface IMyClass
{
    MyEnum Value { get; }
    IMyItemCollection Items { get; }
}

public class MyConcreteClassFactory : MyClassFactoryBase
{
    public override IMyClass Create(MyEnum value)
    {
        var itemBuilder = new MyRemoteItemBuilder();
        var itemCollection = new MyLazyItemCollection(itemBuilder)

        return new MyClass(value, itemCollection);
    }
}
“真正的”代码应该只关心工厂返回IMyClass实例这一事实,而不是具体实现是什么。尽管如此,我还是想测试factory类是否完成了它应该做的事情—构建一个具体的对象图

我是否应该编写一些调用create方法并检查返回对象属性的测试?看起来是这样的,但是如果我需要检查多个类和属性层来验证工厂创建的对象图,这是否仍然适用?这不会导致测试代码,例如:

var created = objectUnderTest.Create(MyEnum.A);
var itemBuilder = (created.Items as MyLazyItemCollection).Builder;
Assert.IsInstanceOfType(itemBuilder, typeof(MyRemoteItemBuilder));
我并不特别喜欢
created.Items
,但在我看来,这将是断言工厂正确创建了
MyLazyItemCollection
的唯一方法,因为并非每个
IMyItemCollection
都有生成器属性。。。这只是图表的第二层。我可能需要进一步挖掘
MyRemoteItemBuilder
的依赖关系,以查看它们是否正确创建:

var service = ((created.Items as MyLazyItemCollection)
   .Builder as MyRemoteItemBuilder).Service;
Assert.IsInstanceOfType(service, typeof(MyService));

我应该以这种方式测试我的工厂,接受难看的嵌套降级-毕竟这是测试代码-还是应该将
IMyItemCollection
构造拉入另一个工厂,并将其作为依赖项添加到我的
MyConcreteClassFactory
(因此我可以从测试代码中注入它,并断言
created.Items
的值是我的模拟工厂创建的实例)。我预计后者将很快导致工厂和工厂的爆炸。毕竟,
MyConcreteClassFactory
的用户不必为她必须提供特定的子工厂而烦恼,是吗?

这当然取决于需要,但我的答案是否定的

您永远不应该以“测试实现(或细节)”的方式来设计您的测试,这种方式在一开始可能会非常好地工作,但过一段时间您就会遇到麻烦。实现的变化非常快,每次更改都会迫使您纠正许多测试用例

相反,您必须“测试行为”。它基本上意味着您对所有细节(具体类)进行抽象,并测试测试一些有价值的场景的案例,而不是细节

我的选择是创建“测试实现”案例,然后我会使用TDD。但稍后它们必须用“测试行为”案例进行重构


这一点非常重要,如果你不仅要说明测试用例的数量,还要说明构建真正安全网的质量。

这是否意味着你根本不会为这个工厂编写单元测试?工厂所做的只是具体类的布线。最终,我将有一套集成测试,如果布线错误,这些测试将失败……是的,可能会失败ly不会按照TDD的格言“在编写测试中的方法之前编写每个测试”,这也意味着我不应该在最后一刻才真正编写我的工厂——因为在进行集成测试之前,我并不真正需要我的具体工厂。我想这是有意义的…+1这是一个很好的问题。