我有一个类,它接受一个MethodInfo实例并从中提取一些信息,但我想模拟这个类。目前很难,因为它需要一个MethodInfo,所以我的计划是为MethodInfo类创建一个包装器并在其上实现一个接口。例如:
public interface IMethodInfo
{
string Name { get; }
}
public class MethodInfoProxy : IMethodInfo
{
private readonly MethodInfo _method;
public MethodInfoProxy(MethodInfo method)
{
_method = method;
}
public string Name { get { return _method.Name; } }
}
public class MyClass
{
public MyClass(IMethodInfo method)
{
...
}
}
另一个例子是File.Exists方法。我们的想法是创建一个IFile.Exists并将它放在一个FileProxy类上,该类只需委托给File.Exists。
由于我是整个单元测试世界的新手,我想知道这是不是一个好的方法?
答案 0 :(得分:3)
这里有两个选项:
那些认为测试不应该改变代码的人和认为应该改变代码的人之间会发生一些宗教战争。依赖注入,如果您要通过创建接口进行模拟,这是必不可少的,这会导致代码具有高内聚和松散耦合以及直观的API。但另一种方法并没有排除这些好处 - 它只是不那么自动。
答案 1 :(得分:1)
我建议尝试将依赖项从类中提取出来 - 而不是提供MethodInfo
(或代理),只需提供Name
。
如果不切实际,你可以编写使用适配器接口的代理类(如你所建议的)或使用像BlackMick或Moles这样的黑魔法工具(只是开玩笑说黑魔法部分:我只是对他们没有任何经验。)
如果您打算使用代理方法,请务必查看SystemWrapper库,该库已经处理了.NET框架中的大约20个类。
答案 2 :(得分:0)
您可以在您使用的每个类周围创建一个包装器,但这样会非常昂贵。最好使用模拟框架,例如Microsoft http://research.microsoft.com/en-us/projects/pex/的moles框架,它也可以存根静态方法。
答案 3 :(得分:0)
Mock类(或假类)将是一个用来满足依赖关系的类,并通过排除依赖项中的问题使测试更具确定性。
public interface IMethodInfo
{
string Name { get; }
}
你的模拟课程:
FakeMethodInfo : IMethodInfo
{
string Name {get {return "FakeMethod";}}
}
现在,在您的单元测试中,将FakeMethodInfo
课程传递到您需要IMethodInfo
的位置。
整个目的是你知道FakeMethodInfo
只返回一个字符串,所以如果出现问题,它不是问题。
不知道MethodInfo在您的程序中有什么上下文。一个更好的例子是
interface IUser
{
string UserName {get;}
}
如果它是在一个类中实现的,那么你将从数据库中获得实际的用户名。
现在,如果你制作一个假的,并传递它,你有点模拟没有真实用户登录的用户,你排除任何问题都与`IUser。
看到我发布的这个大回答你为什么要使用嘲笑。以Moq为例:
Difference between Dependency Injection and Mocking framework (Ninject vs RhinoMock or Moq)
答案 4 :(得分:0)
为了更快地创建包装类,您可以使用我创建的Scaffold代码生成器之一。
https://www.nuget.org/packages/Digitrish.WrapperGenerator/
这将生成可用于任何模拟框架和实际实现的具体包装类的接口。