16

我有以下类,它使用构造函数注入:

public class Service : IService
{
    public Service(IRepository repository, IProvider provider) { ... }
}

对于此类中的大多数方法,我只是为IRepositoryandIProvider和构造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's 的构造函数采用像ints 和strings 这样的简单参数,这很好用,但如果它采用我正在模拟的接口,则不行。你怎么做到这一点?

4

3 回答 3

13

你为什么嘲笑你正在测试的服务?如果您希望测试 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);

我意识到可以在某些框架中模拟具体对象,但是您的预期目的是什么?模拟某些东西背后的想法是删除实际的实现,这样它就不会影响您的测试。但是在您的问题中,您已经说过您希望知道某些类被正确调用,然后您希望验证这些操作的结果。这无疑是在测试实现,因此,我很难看到模拟具体对象的目标。

于 2015-10-05T19:39:28.453 回答
5

当我的等价物Service有一个内部构造函数时,我遇到了一个非常相似的问题,所以 Moq 看不到它。

我添加了

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

到我的 AssemblyInfo.cs 文件以用于实施项目。不确定它是否相关,但我想添加一个建议,以防它对您或其他人有所帮助。

于 2014-11-04T15:39:47.057 回答
1

一定是旧版本的问题,最新版本的一切正常。尼克,请检查!

Ps:我错误地开始赏金(我的构造函数中的签名错误)。

于 2015-10-04T17:42:44.917 回答