Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.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_Design Patterns - Fatal编程技术网

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()
a
static
方法,然后测试静态部分。这种方法的优点(就目前所知)是,它也适用于
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)
    ?否,这意味着我将更改代码,使其不需要/不使用引入状态的内部类变量