我刚刚编写了一个类,并意识到它的所有公共功能都封装在一个方法中。它没有属性,没有共享资源,并且不需要构造函数重载并处理它使用的任何内容。它看起来像这样:
public class ReportGenerator
{
public string GenerateReport(List<SomeClass> stuffToReportOn)
{
string fileName = String.Empty;
using(var reportDs = CreateDataSet(stuffToReportOn))
{
//do the stuff with the third party tool that
//creates the report.
//Construct the filename.
//Save the report.
}
return fileName;
}
private TypedDataSetRequiredByThirdPartyLib CreateDataSet(List<SomeClass> reportItems)
{
//create the dataset, calling two other private methods
//to build the tables/rows
}
}
在我完成重构之后,我意识到这个类可能完全是静态的。我的问题是,应该吗?是否应将在一个公共方法中封装其所有功能的类设为静态?
答案 0 :(得分:5)
没有。什么是预期的好处?
更重要的是潜在的错误。如果在你的类中声明一个静态变量,它只会被初始化一次,它的值将持续存在,并且每个调用的行为可能会有所不同。容易过度查看,这可能很难调试。
答案 1 :(得分:3)
不,它会为这个类 - 或使用这个类的类 - 编写单元测试 - 不可能。
使用像FakeItEasy这样的工具,您甚至不需要该类来实现一个接口就可以模拟它(这意味着您可以快速开始模拟一个未编写的旧代码库)记住TDD,但它无法绕过静态调用。
<强>更新强>
假设您需要对调用GenerateWidgetReports
的方法ReportGenerator.GenerateReport
进行单元测试。您需要确保stuffToReportOn
仅包含Widget1
&amp; Widget2
。你如何编码测试?
你最终要做的是让GenerateWidgetReports
使用名为GetStuffToReportOn
的方法,你可以测试一下,没问题。 GenerateWidgetReports
然后变成调用GetStuffToReportOn
的粘合剂并将其结果传递给ReportGenerator.GenerateReport
。
但是,您仍然无法对GenerateWidgetReports
进行测试,因为如果没有实际生成报告,则无法调用它。
理想情况下,GenerateWidgetReports
的类会获取一个IReportGenerator对象,您可以模拟GenerateReport
方法并在其中测试Widget1
&amp; Widget2
。
如果GenerateReport
是静态的,则无法使用任何模拟工具执行此操作。
更新2
我更正了,TypeMock可以拦截并重定向调用静态方法。 See this answer
答案 2 :(得分:1)
除了单元测试的困难之外,你应该问问自己:
如果你确定让它成为一个静态类适合你,你也可以决定更进一步做一个扩展方法:
public static class ReportExtension
{
public static string GenerateReport(this List<SomeClass> stuffToReportOn)
{
string fileName = String.Empty;
using(var reportDs = CreateDataSet(stuffToReportOn))
{
//do the stuff with the third party tool that
//creates the report.
//Construct the filename.
//Save the report.
}
return fileName;
}
private static TypedDataSetRequiredByThirdPartyLib CreateDataSet(List<SomeClass> reportItems)
{
//create the dataset, calling two other private methods
//to build the tables/rows
}
}
非常确定我的格式是正确的扩展方法。
您仍然遇到单元测试问题,因为代码依赖于此静态方法。最终,您必须自己决定利弊并做出决定。我可能是错的,但是如果您要将依赖代码作为实例类进行单元测试,那么您可以确信它应该可以作为静态或扩展方法使用。
答案 3 :(得分:0)
是的,这样可以更轻松地使用你的课程。