我有以下类,它使用构造函数注入:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
对于本课程中的大多数方法,我只需为IRepository
和IProvider
创建Moq模拟并构造Service
。但是,类中有一个方法可以在同一个类中调用其他几个方法。为了测试这个方法,我不想一起测试所有这些方法,而是测试方法是否正确调用这些方法并正确处理它们的返回值。
执行此操作的最佳方法是模拟Service
。在没有问题之前,我曾经与Moq嘲笑具体的课程。我甚至嘲笑了具体的类,这些类需要Moq的构造函数参数而没有问题。但是,这是我第一次需要将模拟参数传递给模拟对象的构造函数。当然,我试着这样做:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
然而,这不起作用。相反,我收到以下错误:
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
如果Service
的构造函数采用int
和string
s这样的简单参数,这样可以正常工作,但如果它采用我嘲笑的接口则不行。你是怎么做到的?
答案 0 :(得分:6)
你为什么嘲笑你正在测试的服务?如果您希望测试Service类的实现(无论是否是对模拟对象的调用),您只需要对两个接口进行模拟,而不是测试类。
而不是:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
不应该这样吗?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
我意识到在某些框架中模拟具体对象是可能的,但你的目的是什么?模拟某些东西背后的想法是删除实际的实现,以便它不会影响您的测试。但是在您的问题中,您已声明您希望知道正确调用某些类,然后您希望验证这些操作的结果。这无疑是对实施的测试,因此,我很难看到嘲笑具体对象的目标。
答案 1 :(得分:5)
当我的等效Service
有一个内部构造函数时,我遇到了一个非常类似的问题,因此Moq看不到它。
我添加了
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
到我的AssemblyInfo.cs文件中的实现项目。不确定它是否相关,但我想补充一个关于它有助于你或其他人的机会的建议。
答案 2 :(得分:1)
必须是旧版本问题,最新版本都可以。尼克,请检查!
P.s。:我通过错误开始赏金(我的构造函数中有错误的签名)。