无法实例化代理...找不到无参数构造函数

65

我正在尝试使用Moq创建一个单元测试,用于测试MongoDB.AspNet.Identity V2提供程序。这行代码让我非常苦恼:

var appUser = new Mock<PreRegistrationMVC.Models.ApplicationUser>();
var userStore = new Mock<MongoDB.AspNet.Identity.UserStore<PreRegistrationMVC.Models.ApplicationUser>>();

看起来userStore在这里无法正确实例化,以下是错误信息。

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException was unhandled by user code
  HResult=-2147024809
  Message=Can not instantiate proxy of class: MongoDB.AspNet.Identity.UserStore`1[[MVC.Models.ApplicationUser, MVC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
Could not find a parameterless constructor.
  Source=Moq
  StackTrace:
       at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
       at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
       at Moq.Proxy.CastleProxyFactory.CreateProxy(Type mockType, ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
       at Moq.Mock`1.<InitializeInstance>b__2()
       at Moq.PexProtector.Invoke(Action action)
       at Moq.Mock`1.InitializeInstance()
       at Moq.Mock`1.OnGetObject()
       at Moq.Mock.GetObject()
       at Moq.Mock.get_Object()
       at Moq.Mock`1.get_Object()
       at MVC_Tests.Identity.Accounts.AccountController_Test.TestSuccessfulRegister() in c:\Users\Tim\Documents\Visual Studio 2013\Projects\PreRegistrationApp\MVC_Tests\Identity\Accounts\AccountController_Test.cs:line 108
  InnerException: 

我对 Moq 完全陌生,因此想知道:

使用 Moq 实例化需要哪些设置?UserStore 类是否有什么问题无法与 Moq 兼容?

谢谢阅读。

5个回答

57

MOQ适用于模拟接口,但对具体类的处理效果不佳。因此,与其模拟具体类,不如请求接口:

var userStore = new Mock<IUserStore<PreRegistrationMVC.Models.ApplicationUser>>();

同时ApplicationUser应该是POCO,因此无需模拟它,只需在测试中创建其实例而不使用MOQ。


太好了,它起作用了。还有一件事,你能指导我应该模拟哪些东西吗?例如,我正在使用一些层架构,并且我只想测试一层,而我想要测试的那一层也有其他层的依赖关系。你有什么建议? - Naveen Motwani - AIS
@Naveen,你所问的是一个非常广泛的话题,评论区不是讨论的最佳场所。我的建议是阅读一本关于单元测试的书籍——Roy Osherove的其中一本就很好。他详细介绍了你所遇到的问题。 - trailmax

24

您可以尝试参考下面显示的模拟行为:

Mock<testClass>(MockBehavior.Strict, new object[] {"Hello"}); 

9
由于它是params参数,因此可以缩写为new Mock<testClass>(MockBehavior.Strict, "Hello"); - sschoof

21

我知道这是一个晚回复,但我一直在寻找答案,没有找到我需要的准确信息。当创建一个模拟时,您可以将参数传递给所需的构造函数。

例如,如果您有这样的类:

public class Foo
{
    private readonly Boo _boo;

    public Foo(Boo boo)
    {
        _boo = boo;
    }
}

您可以这样模拟:

private readonly Mock<Foo> _foo = new Mock<Foo>(new Mock<Boo>().Object);

18

我有过同样的问题。我曾经写了...

var x = new Mock<Concrete>();

使用...代替...

var x = new Mock<IConcrete>();

-3
在你的ApplicationUser类中添加一个空构造函数。

1
只需在您的模拟构造函数中添加模拟参数即可。 - PmanAce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接