Nic*_*ams 14 class moq mocking concreteclass constructor-injection
我有以下类,它使用构造函数注入:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
Run Code Online (Sandbox Code Playgroud)
对于这个类中的大多数方法,我只是为IRepository和创建Moq模拟IProvider和构造Service.但是,类中有一个方法可以在同一个类中调用其他几个方法.为了测试这个方法,我想测试该方法是否正确地调用这些方法并正确处理它们的返回值,而不是一起测试所有这些方法.
这样做的最好方法是嘲笑Service.我之前没有问题就用Moq模拟了具体的类.我甚至嘲笑了具有Moq构造函数参数的具体类,没有问题.但是,这是我第一次需要将模拟参数传递给模拟对象的构造函数.当然,我试着这样做:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用.相反,我收到以下错误:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service.
Could not find a constructor that would match given arguments:
Castle.Proxies.IRepository
Castle.Proxies.IProvider
Run Code Online (Sandbox Code Playgroud)
如果Service构造函数接受像ints和strings 这样的简单参数,那么这种方法很好,但是如果它接受我正在嘲笑的接口则不行.你怎么做到这一点?
你为什么嘲笑你正在测试的服务?如果您希望测试Service类的实现(无论是否是对模拟对象的调用),您只需要两个接口的模拟,而不是测试类.
代替:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Run Code Online (Sandbox Code Playgroud)
不应该是这样吗?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
Run Code Online (Sandbox Code Playgroud)
我意识到在某些框架中可以模拟具体对象,但你的目的是什么?模拟某些东西背后的想法是删除实际的实现,以便它不会影响您的测试.但是在您的问题中,您已声明您希望知道正确调用某些类,然后您希望验证这些操作的结果.这无疑是对实施的测试,因此,我很难看到嘲笑具体对象的目标.
当我Service有一个内部构造函数时,我遇到了一个非常类似的问题,因此Moq看不到它.
我补充道
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Run Code Online (Sandbox Code Playgroud)
到我的AssemblyInfo.cs文件中的实现项目.不确定它是否相关,但我想补充一个关于它有助于你或其他人的机会的建议.