我正在使用Windows 7中的C#开发.NET 4.0。
我想测试一些使用mock的方法之间的通信。唯一的问题是我想在没有实现接口的情况下这样做。那可能吗?我刚刚阅读了很多关于模拟对象的主题和一些教程,但是它们都用于模拟接口,而不是类。我尝试使用Rhino和Moq框架。
答案 0 :(得分:50)
只需将您需要伪造的任何方法标记为virtual
(而不是私有)。然后,您将能够创建一个可以覆盖该方法的假货。
如果您使用new Mock<Type>
并且没有无参数构造函数,那么您可以将参数作为上述调用的参数传递,因为它采用param Objects
答案 1 :(得分:18)
大多数模拟框架(包括Moq和RhinoMocks)生成代理类作为模拟类的替代,并使用您定义的行为覆盖虚拟方法。因此,您只能在具体或抽象类上模拟接口或虚拟方法。另外,如果你在嘲笑一个具体的类,你几乎总是需要提供一个无参数的构造函数,以便模拟框架知道如何实例化该类。
为什么厌恶在代码中创建接口?
答案 2 :(得分:12)
使用MoQ,您可以模拟具体类:
var mocked = new Mock<MyConcreteClass>();
但是这允许您覆盖virtual
代码(方法和属性)。
答案 3 :(得分:6)
标准模拟框架正在创建代理类。这就是他们在技术上限于接口和虚拟方法的原因。
如果您想要模拟“普通”方法,则需要一个可以使用检测而不是代理生成的工具。例如。 MS Moles和Typemock可以做到这一点。但前者有一个可怕的“API”,后者是商业性的。
答案 4 :(得分:5)
我认为为该类创建一个接口会更好。并使用界面创建单元测试。
如果您无法访问该类,则可以为该类创建适配器。
例如:
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轻松地为您的类创建模拟。
希望它有效。
答案 5 :(得分:4)
如果您无法更改受测试的课程,那么我建议的唯一选择是使用MS Fakes https://msdn.microsoft.com/en-us/library/hh549175.aspx。 但是,MS Fakes仅适用于几个版本的Visual Studio。
答案 6 :(得分:1)
如果情况变得更糟,您可以创建一个接口和适配器对。 您可以更改ConcreteClass的所有用法来改为使用接口,并始终在生产代码中传递适配器而不是具体类。
适配器实现接口,因此mock也可以实现接口。
它不仅仅是创建虚拟方法或仅添加接口,而且如果您无法访问具体类的源,它可以让您脱离绑定。
答案 7 :(得分:1)
我在其中的一个旧项目和遗留项目中遇到过类似的问题,其中包含任何接口或最佳实践,而且由于项目的成熟,实施它们或重构代码太难了业务,所以在我的UnitTest项目中,我曾经在我想要模拟的类上创建一个Wrapper,并且包装器实现接口包含我想要设置和使用的所有我需要的方法,现在我可以模拟包装器而不是真实的课程。
例如:
您要测试的服务不包含虚拟方法或实现接口
public class ServiceA{
public void A(){}
public String B(){}
}
包裹到moq
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(...);
}
这可能不是最佳做法,但如果您的项目规则以这种方式强迫您,请执行此操作。同时将所有Wrappers放入单元测试项目或仅为单元测试指定的Helper项目中,以免使用不需要的包装器或适配器使项目过载。
<强>更新强> 这个答案来自一年多,但在今年我遇到了很多类似的场景,有不同的解决方案。 例如,使用Microsoft Fake Framework轻松创建模拟,伪造和存根,甚至可以在没有任何接口的情况下测试私有和受保护的方法。 您可以阅读:https://docs.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2017