Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.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#_Visual Studio_Unit Testing - Fatal编程技术网

C# 良好的软件设计模式,用于单元测试的构造函数重载

C# 良好的软件设计模式,用于单元测试的构造函数重载,c#,visual-studio,unit-testing,C#,Visual Studio,Unit Testing,我正在用c语言开发一个windows窗体应用程序。在实例化表单时,我在构造函数中初始化了几个硬件类。硬件1、硬件2、硬件3表示我在软件中实例化的硬件类 public partial class Form1 { Hardware1 a; Hardware2 b; Hardware3 c; public Form1() { // initialize hardware1,2 and 3 using native dll calls of a,b an

我正在用c语言开发一个windows窗体应用程序。在实例化表单时,我在构造函数中初始化了几个硬件类。硬件1、硬件2、硬件3表示我在软件中实例化的硬件类

public partial class Form1 {
    Hardware1 a;
    Hardware2 b;
    Hardware3 c;

    public Form1() {
        // initialize hardware1,2 and 3 using native dll calls of a,b and c
    }
我想在我的主窗体中对此方法进行单元测试

public int MyMethod(int percent, ref double power) {
    for(int i =0; i<3; i++)
        {
            if(a.isValid)
            {
                b.DoThing1(percent);
                b.DoThing2(true);
                c.DoSomething1();
                double val = C.DoSomething2();
                if (val != -500)
                {
                    power = val;
                    return 0;
                }
            }
            else
                return 1;

        }
        return 2; 
    }
或者我应该为硬件1A、硬件2B和硬件3C提供接口吗?我了解到,通常最好用接口来代替具体的类


什么是单元测试的良好软件实践Form1 myMethod

使用接口的最大优点是,单元测试可以定义自己的接口实现,这允许单元测试在没有外部依赖的情况下执行

我建议您将MyMethod从表单中删除,并将其放入自己的类中。一般来说,将业务与演示分开总是一个好主意

以下是我的建议:

public interface IHardware1 { }
public interface IHardware2 { }
public interface IHardware3 { }

public class Hardware1 : IHardware1 { }
public class Hardware2 : IHardware2 { }
public class Hardware3 : IHardware3 { }


public class MyClass
{
    private IHardware1 _a;
    private IHardware2 _b;
    private IHardware3 _c;

    public MyClass( IHardware1 hardware1, IHardware2 hardware2, IHardware3 hardware3 )
    {
        _a = hardware1;
        _b = hardware2;
        _c = hardware3;
    }

    public int MyMethod( int percent, ref double power )
    {
        ...
            _b.DoThing1( percent );
            _b.DoThing2( true );
            _c.DoSomething1();
        ...
    }
}
然后在您的表单中,以及在您的单元测试项目中,您只需使用:

MyClass _myClass = new MyClass( a, b, c);
_myClass.MyMethod( x, y );

我建议在C中使用NUnit和NSubstitute进行单元测试

你说的对,测试接口比测试实际实现更好。 使用NSubstitute,您可以模拟接口并设置该接口中声明的所有方法的返回值:

//Test
var someType = Substitute.For<ISomeType>();
var someParameter = 42;
var someReturnValue = 1;
someType.SomeMethod(someParameter).Returns(someReturnValue);
var sut = new SomeClass(someType); //sut means system under test
var result = sut.AMethod();
//This would test positive as you set the return value of SomeMethod to 1 
//in case it gets called with a value of 42
Assert.That(result, Is.EqualTo(someReturnValue));
//Test end

//This would be the class you want to unit test
public class SomeClass
{
    private ISomeType someType;

    public SomeClass(ISomeType someType)
    {
        this.someType = someType;
    }

    public int AMethod()
    {
        return someType.SomeMethod(42);
    }
}
这里发生的情况是,您的测试模拟SomeType,并将其方法somethod的返回值设置为1(如果使用参数42调用)


通过这种方式,您可以轻松控制调用某个方法时从模拟服务中获得的值。

在softwareengineering.stackexchange.com上有一个关于为单元测试使用单独构造函数的问题。嘿,谢谢你的回答!我目前正在使用Moq进行单元测试c,同时使用mstest。之所以在主窗体中使用它,是因为必须在MyMethod函数中访问hardware1 2和3类,而MyMethod函数仅在主窗体中可用
//Test
var someType = Substitute.For<ISomeType>();
var someParameter = 42;
var someReturnValue = 1;
someType.SomeMethod(someParameter).Returns(someReturnValue);
var sut = new SomeClass(someType); //sut means system under test
var result = sut.AMethod();
//This would test positive as you set the return value of SomeMethod to 1 
//in case it gets called with a value of 42
Assert.That(result, Is.EqualTo(someReturnValue));
//Test end

//This would be the class you want to unit test
public class SomeClass
{
    private ISomeType someType;

    public SomeClass(ISomeType someType)
    {
        this.someType = someType;
    }

    public int AMethod()
    {
        return someType.SomeMethod(42);
    }
}