C# 良好的软件设计模式,用于单元测试的构造函数重载
我正在用c语言开发一个windows窗体应用程序。在实例化表单时,我在构造函数中初始化了几个硬件类。硬件1、硬件2、硬件3表示我在软件中实例化的硬件类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
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);
}
}