我正在Windows 7中使用C#在.NET 4.0上工作。
我想使用模拟测试某些方法之间的通信。唯一的问题是我想在不实现接口的情况下做到这一点。那可能吗?
我刚刚阅读了很多关于模拟对象的主题和一些教程,但是它们全部都用于模拟接口,而不是类。我尝试使用Rhino和Moq框架。
我正在Windows 7中使用C#在.NET 4.0上工作。
我想使用模拟测试某些方法之间的通信。唯一的问题是我想在不实现接口的情况下做到这一点。那可能吗?
我刚刚阅读了很多关于模拟对象的主题和一些教程,但是它们全部都用于模拟接口,而不是类。我尝试使用Rhino和Moq框架。
Answers:
只需将您需要伪造的任何方法标记为virtual
(而非私有)即可。然后,您将能够创建可以覆盖该方法的伪造品。
如果使用new Mock<Type>
并且没有无参数构造函数,则可以将参数作为上述调用的参数传递,因为它采用了param Objects
大多数模拟框架(包括Moq和RhinoMocks)都会生成代理类来代替模拟类,并使用定义的行为覆盖虚拟方法。因此,您只能在具体或抽象类上模拟接口或虚拟方法。另外,如果要模拟具体的类,则几乎总是需要提供无参数的构造函数,以便模拟框架知道如何实例化该类。
为什么不喜欢在代码中创建接口?
使用MoQ,您可以模拟具体的类:
var mocked = new Mock<MyConcreteClass>();
但这使您可以覆盖virtual
代码(方法和属性)。
new Mock<MyConcreteClass>(param1, anotherParam, thirdParam, evenMoreParams);
我认为最好为该类创建一个接口。并使用界面创建单元测试。
如果您无权访问该类,则可以为该类创建适配器。
例如:
public class RealClass
{
int DoSomething(string input)
{
// real implementation here
}
}
public interface IRealClassAdapter
{
int DoSomething(string input);
}
public class RealClassAdapter : IRealClassAdapter
{
readonly RealClass _realClass;
public RealClassAdapter() => _realClass = new RealClass();
int DoSomething(string input) => _realClass.DoSomething(input);
}
这样,您可以使用IRealClassAdapter轻松为类创建模拟。
希望它能工作。
标准的模拟框架正在创建代理类。这就是为什么它们在技术上仅限于接口和虚拟方法的原因。
如果您还想模拟“常规”方法,则需要一个可与检测配合使用而不是生成代理的工具。例如,MS Moles和Typemock可以做到这一点。但是前者有一个可怕的“ API”,而后者是商业化的。
如果您不能更改测试中的类,那么我建议的唯一选择是使用MS Fakes https://msdn.microsoft.com/zh-cn/library/hh549175.aspx。但是,MS Fakes仅在Visual Studio的几个版本中起作用。
在我从事的一个旧项目中,我遇到了类似的问题,其中不包含任何接口或最佳实践,而且由于项目业务的成熟,很难再次强制他们重新构建内容或重构代码,因此在我的UnitTest项目中,我曾经在要模拟的类和该包装器实现接口上创建了一个包装器,该接口包含了我想要设置和使用的所有所需方法,现在我可以模拟包装器而不是真实类。
例如:
您要测试的服务不包含虚拟方法或实现接口
public class ServiceA{
public void A(){}
public String B(){}
}
包装起订量
public class ServiceAWrapper : IServiceAWrapper{
public void A(){}
public String B(){}
}
包装器界面
public interface IServiceAWrapper{
void A();
String B();
}
在单元测试中,您现在可以模拟包装器:
public void A_Run_ChangeStateOfX()
{
var moq = new Mock<IServiceAWrapper>();
moq.Setup(...);
}
这可能不是最佳实践,但是如果您的项目规则以这种方式强迫您执行此操作。还要将所有包装器放入仅为单元测试指定的单元测试项目或帮助器项目中,以免不必要的包装器或适配器使项目过载。
更新: 这个答案来自一年多的时间,但是在今年,我遇到了许多使用不同解决方案的类似情况。例如,使用Microsoft Fake Framework创建模拟,伪造品和存根,甚至测试没有任何接口的私有方法和受保护方法非常容易。您可以阅读:https : //docs.microsoft.com/zh-cn/visualstudio/test/isolate-code-under-test-with-microsoft-fakes?view=vs-2017