65

I am trying to create a unit test using Moq which tests the MongoDB.AspNet.Identity V2 provider. This line is giving me grief:

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

It seems the userStore won't instantiate properly here is the error.

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: 

I am completely new to Moq so I am looking for: What type of settings are needed for Moq to instantiate this? Is there something about the UserStore class that won't play well with Moq?

Thanks for reading.

ChiliYago
  • 11,341
  • 23
  • 79
  • 126

5 Answers5

55

MOQ is good for mocking interfaces, but does not work so well with concrete classes. So instead of mocking concrete class, ask for the inteface:

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

Also ApplicationUser should be POCO, so no need to mock it, just create its instance without MOQ and use in tests.

trailmax
  • 34,305
  • 22
  • 140
  • 234
  • Great it worked. One more thing could you also guide me what are the things I should Mock. For example I am working with some tier architecture and I just want to test one tier and the tier I want to test it has some other tier dependency as well. So what do you should suggest? – Naveen Motwani - AIS Jun 17 '16 at 13:48
  • @Naveen what you ask is a very broad topic and comments is not the best place for a discussion. My recommendation is to read a book about unit testing - one from Roy Osherove is good. He goes into details about problem you are having. – trailmax Jun 17 '16 at 14:20
24

You can try referring Mock behavior,as shown below

Mock<testClass>(MockBehavior.Strict, new object[] {"Hello"}); 
Ashraf Alam
  • 3,500
  • 32
  • 31
  • 9
    Since it is params Parameter it could be written shorter as `new Mock(MockBehavior.Strict, "Hello");` – sschoof Feb 07 '17 at 13:39
19

I know this is a late response, but I was looking for an answer and couldn't find exactly what I needed, but when creating a mock, you can pass the parameters to your wanted constructor.

So for example if you have class like this:

public class Foo
{
    private readonly Boo _boo;

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

You can mock it like this:

private readonly Mock<Foo> _foo = new Mock<Foo>(new Mock<Boo>().Object);
merlinabarzda
  • 668
  • 5
  • 15
18

I had this problem. I had written...

var x = new Mock<Concrete>();

... instead of ...

var x = new Mock<IConcrete>();
Remotec
  • 10,304
  • 25
  • 105
  • 147
-3

Add an empty constructor to your ApplicationUser class.

M.Simionov
  • 17
  • 7