Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking - cannot instantiate proxy class of property?

Inside my tests, here is my code:

[SetUp]
public void Initialise()
{
    mockOwinManager = new Mock<IOwinManager<ApplicationUser, ApplicationRole>>();
    mockSearch = new Mock<ISearch<ApplicationUser>>();
    mockMail = new Mock<IRpdbMail>();
    mockUserStore = new Mock<IUserStore<ApplicationUser>>();

    mockOwinManager.Setup(x => x.UserManager).Returns(() => new AppUserManager(mockUserStore.Object));

    sut = new UsersController(mockOwinManager.Object, mockSearch.Object, mockMail.Object);
}

And then the test itself:

[Test]
public void WhenPut_IfUserIsNullReturnInternalServerError()
{
    //Arrange
    mockOwinManager.Setup(x => x.UserManager.FindByIdAsync(It.IsAny<string>())).Returns(() => null);

    //Act
    var response = sut.Put(new AppPersonUpdate());

    //Assert
    Assert.AreEqual(response.Result.StatusCode, HttpStatusCode.InternalServerError);
}

But my arrange line throws the following error:

Can not instantiate proxy of class: Microsoft.AspNet.Identity.UserManager`1[[SWDB.BusinessLayer.Identity.ApplicationUser, SWDB.BusinessLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]. Could not find a parameterless constructor.

Why is this so, since in Setup I've set my mockOwinManager's UserManager property in what I'd like it to return already?

like image 773
Evangelos Aktoudianakis Avatar asked Dec 25 '15 13:12

Evangelos Aktoudianakis


2 Answers

Create a mock object of UserManager first. Then setup its virtual method FindByIdAsync(given that the type of the property UserManager is a class AppUserManager and lets say this class implements IAppUserManager).

var yourMockOfUserManager = new Mock<IAppUserManager>();
yourMockOfUserManage.Setup(x=>x.FindByIdAsync(It.IsAny<string>())).Returns(() => null);

and finally

mockOwinManager.Setup(x => x.UserManager).Returns(() => yourMockOfUserManager.Object);
like image 87
Afaq Avatar answered Oct 30 '22 03:10

Afaq


UserManager class accepts IUserStore<ApplicationUser> in a constructor, which is used to get an access to FindByIdAsync and etc

When I need to test classes which require UserManager, I do mock for IUserStore and setup its FindByIdAsync method, then I create an instance of UserManager and provide my mock into its parameters. This is a class constructor which requires UserManager:

internal class UserManagerWrapper
{
    private readonly IEditUserResponceDataModelProvider _editUserResponceDataModelProvider;
    private readonly UserManager<User> _userManager;
    private readonly IUserModelFactory _userModelFactory;

    public UserManagerWrapper(UserManager<User> userManager,
        IUserModelFactory userModelFactory,
        IEditUserResponceDataModelProvider editUserResponceDataModelProvider)
    {
        _userManager = userManager;
        _userModelFactory = userModelFactory;
        _editUserResponceDataModelProvider = editUserResponceDataModelProvider;
    }

    public async Task<IUserModel> FindByIdAsync(string id)
    {      
        var user = await _userManager.FindByIdAsync(id);
        return _userModelFactory.Create(user.Id, user.Email, user.Year, user.UserName);
    }
}

This is my test for UserManagerWrapper:

private Mock<IUserStore<User>> UserStoreMock { get; set; }

[SetUp]
public void SetUp()
{
    UserStoreMock = new Mock<IUserStore<User>>();
    UserStoreMock.Setup(x => x.FindByIdAsync(It.IsAny<string>(), CancellationToken.None))
        .Returns(Task.FromResult(new User() {Year = 2020}));
}

[TestCase(2020)]
public async Task ValidateUserYear(int year)
{

    var userManager = new UserManager<User>(UserStoreMock.Object, null, null, null, null, null, null, null, null);

    var userManagerWrapper = new UserManagerWrapper(userManager, new UserModelFactory(), null);
    var findByIdAsync = await userManagerWrapper.FindByIdAsync("1");
    Assert.AreEqual(findByIdAsync.Year, year);
}`:
like image 45
Anastasia Danilova Avatar answered Oct 30 '22 05:10

Anastasia Danilova