C# 测试使用类属性的方法
假设我有一个类,它有一个计算某些东西的方法(不管是什么)。它可能看起来像这样:C# 测试使用类属性的方法,c#,unit-testing,design-patterns,C#,Unit Testing,Design Patterns,假设我有一个类,它有一个计算某些东西的方法(不管是什么)。它可能看起来像这样: class Example { public int CalculateStuff(int inputValue) { // ...some logic here } } class Example { public int InputValue { get; set; } public int CalculateStuff() {
class Example
{
public int CalculateStuff(int inputValue)
{
// ...some logic here
}
}
class Example
{
public int InputValue { get; set; }
public int CalculateStuff()
{
// ...calculate something from 'InputValue'
}
}
void UnitTest()
{
var example = new Example();
example.InputValue = 42;
Assert.AreEqual(84, example.CalculateStuff());
}
var result = example.CalculateDateStuff(DateTime.Now);
但是,inputValue
总是取自类本身。所以它可以看起来像这样:
class Example
{
public int CalculateStuff(int inputValue)
{
// ...some logic here
}
}
class Example
{
public int InputValue { get; set; }
public int CalculateStuff()
{
// ...calculate something from 'InputValue'
}
}
void UnitTest()
{
var example = new Example();
example.InputValue = 42;
Assert.AreEqual(84, example.CalculateStuff());
}
var result = example.CalculateDateStuff(DateTime.Now);
现在这很好,但我想在CalculateStuff()
中添加一个单元测试,所以我的问题是:
什么是进行清晰测试的最佳方法?我可以在测试中简单地设置类的值,如下所示:
class Example
{
public int CalculateStuff(int inputValue)
{
// ...some logic here
}
}
class Example
{
public int InputValue { get; set; }
public int CalculateStuff()
{
// ...calculate something from 'InputValue'
}
}
void UnitTest()
{
var example = new Example();
example.InputValue = 42;
Assert.AreEqual(84, example.CalculateStuff());
}
var result = example.CalculateDateStuff(DateTime.Now);
但是,我也可以使用非静态重载创建CalculateStuff()
astatic
方法,然后测试静态部分。这种方法的优点(就目前所知)是,它也适用于InputValue
类似于DateTime的场景
class Example
{
public int InputValue { get; set; }
public int CalculateStuff()
{
return CalculateStuff(InputValue);
}
public static int CalculateStuff(int inputValue)
{
// ...calculate something from 'inputValue'
}
}
void UnitTest()
{
Assert.AreEqual(84, Example.CalculateStuff(42));
}
有没有一种被广泛接受的方法?如果是,哪一个?还是取决于具体情况
更新
另一个稍有不同(但属于同一类别)的示例是,如果输入类型为DateTime
,则在生产中总是使用DateTime.Now
作为输入(例如计算自某个事件以来的时间)。这意味着示例
类始终有一个值为DateTime.Now
的属性,如果遵循第一种方法:
public int CalculateDateStuff(DateTime untilDtm)
{
// ...logic and stuff
}
这就是所谓的:
class Example
{
public int CalculateStuff(int inputValue)
{
// ...some logic here
}
}
class Example
{
public int InputValue { get; set; }
public int CalculateStuff()
{
// ...calculate something from 'InputValue'
}
}
void UnitTest()
{
var example = new Example();
example.InputValue = 42;
Assert.AreEqual(84, example.CalculateStuff());
}
var result = example.CalculateDateStuff(DateTime.Now);
…至少如果它是可测试的。这只是我的观点,但是如果您使用的是单元测试,那么您必须尝试测试您通常对代码执行的操作。使用不同的输入,但就像您使用的一样
第一个示例看起来像是您在代码中使用的一个案例:创建一个类,填充它,然后调用该方法
第二种,在我看来,似乎把所有情况都复杂化了,因为它与实际情况完全不同,而且您必须为每个特定情况添加代码
想象一下,您有10个属性和10个方法:这个类可以增长多少?您不应该添加额外的方法,只是为了测试其他方法。你所做的是正确的。通常,单元测试包括3个步骤(步骤的命名可能会有所不同):
设置:准备测试所需的一切
操作:运行要测试的方法
断言:对照预期的输出检查操作结果
就你而言:
void UnitTest()
{
//Setup
var example = new Example();
example.InputValue = 42;
//Action
var result = example.CalculateStuff()
//Assert
Assert.AreEqual(84, result);
}
只有拥有清晰的代码,才能编写清晰的测试
在第一个示例中,将所需内容传递给方法是最简单的方法
为什么??因为输入是测试方法的一部分。如果您的输入是类本身的一部分,那么您将失去清晰度。这段代码现在可能很简单,但以后很容易变成其他代码。您现在有了在测试方法之外的数据,这意味着您现在必须维护状态。不要那样做
对于其他类型的数据,如DateTime,答案是相同的,DateTime值是一个参数,您可以将DateTime.Now传递给您的方法
总之,如果有选择的话,我会一直坚持这个观点:
public int CalculateStuff(int inputValue)
{
// ...some logic here
}
前者似乎很简单,我看不出后者有什么好处。对于前者,您遇到了什么问题?@David,如果输入值是DateTime
,并且该值始终是DateTime。例如,现在是。这样,您就必须在示例
类上创建一个属性,它总是设置为日期时间。现在
,这似乎有点奇怪。它是TDD吗?你为什么说“我也可以做”?至于使方法保持静态与否,这是非常重要的。我认为两者没有区别。您将测试完全相同的算法。但一般来说,我会测试代码中使用的对象和方法。因此,第一个选择是前进的道路。特别是,当方法依赖于私有变量/对象状态时。@JakobBuskSørensen:所示代码中没有DateTime
。如果输入必须始终是DateTime.Now
,那么为什么需要提供它呢?为什么该方法不能只使用DateTime.Now
?我还不清楚你想解决什么问题。说得对。例如,输入值为DateTime
且值为DateTime.Now
?您可以设置example.InputValue=DateTime。现在在UnitTest中,这是否意味着在测试外部调用时,您会这样调用它:var result=example.CalculateStuff(example.InputValue)
?否,这意味着我将更改代码,使其不需要/不使用引入状态的内部类变量