我对单元测试非常陌生,虽然我花了大量的时间在研究上,但我无法找到适合我的情况的正确方法。
我的代码库非常庞大(大约3年的工作时间),不幸的是,很难进行测试,也从来没有对其进行过单元测试。
因此,例如,在尝试测试集合类ProductCollection (更具体地说,它的bool MoveElementAtIndex(Product productToMove, int newIndex) )时,我遇到了以下问题:
new ProductCollection()new KeyedList<ID, Product>。我认为不应该在这个构造函数中调用它,因为我没有测试KeyedList。ProductCollection添加3种产品。new Product()。Product类的构造函数做了几件事this.ID = IDUtils.ComputeNewIDBasedOnTheMoonPhase()的唯一ID。我想我也不应该测试这个,因为这不是我的范围。在这种深度下,我应该如何避免这样的呼吁呢?this.Properties = new ProductProperties(folderPathToDefaultProperties)。这不应该从我的简单FieldCollection.MoveElementAtIndex测试中调用,对吗?ProductCollection.Add(MyProduct)检查底层KeyedList是否已经包含了该产品。这也是我应该避免的业务逻辑,与我的测试无关。问题是怎么做?Add方法中,会引发一些事件,通知系统一些事情(例如,向集合添加了一个新产品)。我认为也不应该发射这些武器。KeyedList实际上包含这些字段,它调用KeyedList.Remove(),调用KeyedList.Insert()作为其移动逻辑,并触发像CollectionModified这样的事件。如果您能解释一下如何正确地进行这个单元测试,如何避免底层对象被调用,我将非常感激。
我想到的是微软的Moles (VS2010),因为我的印象是它不需要我重构所有东西,因为这绝对不是一种选择。但是已经试过了,仍然找不到合适的方法来使用它。
而且,我有这样的印象,这个具体的例子将对我的处境中的许多人有所帮助,因为现实世界中的代码就是这样的。
有什么想法吗?
发布于 2013-01-12 15:53:54
您的代码在设计时没有考虑到单元测试,这使得这样做非常困难。我建议您正确地设计和单元测试您的新代码,并尝试重构最重要的事情,以便您可以对其进行单元测试。
示例:
但是Product的构造函数做了几件事。它计算新创建的产品的唯一ID : this.ID = IDUtils.ComputeNewIDBasedOnTheMoonPhase()。我想我也不应该测试这个,因为这不是我的范围。在这种深度下,我应该如何避免这样的呼吁呢?
要解决这个问题,您应该将一个接口IUtils传递给产品构造函数。要测试产品类,您可以创建一个IUtils的模拟,它返回一个设置值。你也可以用你的ProductProperties做同样的事情。
此外,在这个Add方法中,会引发一些事件,通知系统一些事情(例如,向集合添加了一个新产品)。我认为也不应该发射这些武器。
这取决于设计。您可以使用观察者模式,而在单元测试时没有任何观察者。
发布于 2013-01-12 16:00:01
这是一个常见的问题,也是为什么我们有框架来为我们伪造对象。存根或模拟允许我们在类周围创建测试工具,而不必实例化许多其他类和服务。有许多suchh框架。这是一个非常有用的博客,包含三个常见的框架。http://www.richard-banks.org/2010/07/mocking-comparison-part-1-basics.html。
我对单元测试非常陌生,并且发现的“单元测试的艺术”一书非常有用。罗伊有一个博客,这些是他在单元测试http://osherove.com/display/Search?moduleId=10002929&searchQuery=Unit+Testing上的一些帖子
需要考虑的另一件事是,您的类之间的耦合有多紧密。这可能不是那么容易做到,但您可能想看看依赖注入。这使得类可以更松散地耦合,因此更容易测试。我发现Mark在.NET中的“依赖注入”是一个很好的介绍。
在我的研究之后,我将NUnit作为测试框架,NSubstitute用于模拟和存根,流利断言使编写测试更容易,而NInject用于依赖注入
发布于 2013-01-12 16:01:12
我建议使用ApprovalTest。这是一个很好的工具来开始测试遗留系统,而不是最好的设计。
现在不要在单元测试和集成测试之间进行区分,也不要费心完全隔离类。您的代码可能并不最适合于可测试性,并且当您开始将所有内容彼此隔离时,您将得到大量的排列部分,并且测试非常脆弱。
另一方面,您必须隔离外部资源(web服务、数据库、文件系统等)。此外,所有不确定的行为都应该隔离(Random、当前时间、用户输入等等)。
我只是建议创建一个验证测试的安全网,这将帮助您在可测试性的方向上更改软件,并将告诉您是否对代码进行了彻底的更改。
读迈克尔羽毛有效地使用遗产代码
https://stackoverflow.com/questions/14294861
复制相似问题