39

I have a class with Microsoft.AspNet.Identity.UserManager injected, and I want to expect the userManager.CreateAsync(user, password) method to return a Task where the IdentityResult.Succeeded = true. However, the only available constructors for IdentityResult are failure constructors that will cause Succeeded property to be false.

How does one create an IdentityResult that has Succeeded == true? IdentityResult doesn't implement an interface and Succeeded isn't virtual so I don't see any obvious ways of creating a mock object through Rhino Mocks (which i'm using as my mocking framework).

My method does something like the below. Providing this example to show why I might want to mock this.

  public async Task<IdentityResult> RegisterUser(NewUser newUser)
    {
        ApplicationUser newApplicationUser = new ApplicationUser()
        {
            UserName = newUser.UserName,
            Email = newUser.Email
        };

        IdentityResult identityResult = await applicationUserManager.CreateAsync(newApplicationUser, newUser.Password);

        if(identityResult.Succeeded)
        {
            someOtherDependency.DoSomethingAmazing();
        }

        return identityResult;
    }

I'm trying to write a unit test that ensures that someOtherDependency.DoSomethingAmazing() is called if identityResult.Succeeded is true. Thanks for any help!

jakejgordon
  • 4,008
  • 7
  • 36
  • 45
  • Sounds like a case for a decorator (http://en.wikipedia.org/wiki/Decorator_pattern). – Preston Guillot Oct 09 '14 at 01:56
  • Yeah I was really trying to reserve that as a last resort. There are a number of methods that return IdentityResult so it would be a pain to wrap all of these.... but I may just have to. – jakejgordon Oct 09 '14 at 02:38
  • As @jaytre mentioned, use var result = IdentityResult.Success will give you an IdentityResult object with Succeeded = true – Suhas Joshi Oct 09 '14 at 19:43

5 Answers5

60

Would the static IdentityResult.Success property work? http://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.identityresult.success(v=vs.108).aspx

Edit: To add some more detail, it seems what you want to do is get your mocked CreateAsync to return an IdentityResult where Suceeded is true. For that I would just return IdentityResult.Success from your mock. There's shouldn't be a need to mock the IdentityResult itself.

Example: How to setup a service that returns Successful identity result.

    applicationUserManagerMock.Setup(s => 
        s.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>())
    ).ReturnsAsync(IdentityResult.Success);
jt000
  • 3,196
  • 1
  • 18
  • 36
  • What exactly are you suggesting here? I need to force the Success value to be true for my test. – jakejgordon Oct 09 '14 at 11:30
  • 1
    Maybe I'm mistaken with what you want to do, but I would mock out CreateAsync to return IdentityResult.Success. I don't think there's a need to mock out IdentityResult. Just CreateAsync to provide the functionality that you're expecting. – jt000 Oct 09 '14 at 13:10
  • 4
    Ah, I misunderstood what this was. The static property actually returns an IdentityResult that is successful. Weird. Anyway, that is indeed exactly what I need. Thanks! – jakejgordon Oct 10 '14 at 01:00
  • 3
    Might be worth stating more clearly - the way to get a "Succeeded" result is to use the IdentityResult.Success static property to generate the instance of the result with Succeeded == true. It is the only way I can see to get a +ve response. – Ian Robertson Apr 23 '15 at 16:32
  • What about returning an `IdentityResult` that failed? – DevEng Jul 16 '18 at 14:54
  • Been a while since I used this code, but I think `return new IdentityResult("FAILED");` would do it... https://learn.microsoft.com/en-us/previous-versions/aspnet/web-frameworks/dn315342(v%3dvs.108) – jt000 Jul 17 '18 at 19:42
  • Exactly what I needed. – Jeremy Ray Brown Feb 21 '19 at 22:17
  • Unable to get IdentityResult https://stackoverflow.com/questions/59387380/asp-net-core-unit-test-mock-usermanager-createasync-and-return-identity-result – Ravi Dec 18 '19 at 10:51
23

To make the Succeeded property equal to True use either of these examples:

return IdentityResult.Success;
IdentityResult result = IdentityResult.Success;
Sabel
  • 559
  • 9
  • 14
4

Further more, to make the Success property returns true

return Identity.Success;

Then in your implementing code, call the implementing method like this

var result = await RegisterUser(newUser).Result
if(result.Succeeded)
{
  //do something
}
mcemmy
  • 9,232
  • 1
  • 11
  • 4
4

Approach is different for Microsoft.AspNet.Identity and Microsoft.AspNetCore.Identity. Bellow I provided solutions for both:

  1. If you are using Microsoft.AspNet.Identity namespace please check following approach:

    In my example I mocked IdentityResult.Success in following way:

    First, IdentityResult has protected constructor:

    protected IdentityResult(bool success);
    

    Protected constructor can be accessed from inherited class if you implement like this:

        public class IdentityResultMock : IdentityResult
        {
            public IdentityResultMock(bool succeeded) : base(succeeded) { }
        }
    

    Second, in my unit test I configured ResetPasswordAsync() to return identityResult like in below:

    var identityResult = new IdentityResultMock(true);
    _mockUserManager.Setup(e => e.ResetPasswordAsync(user.Id, model.Code, model.Password)).ReturnsAsync(identityResult);
    

    Third, in my controller's action ResetPasswordAsync() will returns result with Successed == true:

    var result = await userManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
    

    Basically I implemented new class which inherited IdentityResult and used that in my test cases.

  2. If you are using using Microsoft.AspNetCore.Identity namespace then try following approach:

    IdentityResult in this case does't have protected constructor but it has protected property Succeeded which can be accessed within class who inherited IdentityResult.

    We can achieve like in following example:

    public class IdentityResultMock : IdentityResult
    {
        public IdentityResultMock(bool succeeded = false)
        {
            this.Succeeded = succeeded;
        }
    }
    
    var result = new IdentityResultMock(true);
    Console.WriteLine(result.Succeeded);
    
    result.Succeeded = true; // This is not allowed! Please use constructor.
    
kat1330
  • 5,134
  • 7
  • 38
  • 61
  • I tried this but in the public IdentityResultMock(bool succeeded) : base(succeeded) { } I am getting error "IdentityResult doesn't take a constructor with one argument".. Am I doing it correctly? – Alexander Aug 23 '19 at 08:49
  • @Alexander I am not sure what did you try but `IdentityResult` has protected constructor which accept bool. Please see source code: https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Core/IdentityResult.cs Did you use from namespace: `Microsoft.AspNet.Identity`? – kat1330 Aug 23 '19 at 16:59
  • I am using Microsoft.AspNetCore.Identity namespace. And I find no constructor accepting bool succeeded. For aspnetcore, is this done differently? – Alexander Aug 23 '19 at 18:21
  • @Alexander It looks like that `IdentityResult` from `Microsoft.AspNetCore.Identity` namespace has only default constructor. It means that my solution will not work for that case :( – kat1330 Aug 23 '19 at 18:33
  • @Alexander I updated answer which has solution for AspNetCore as well. – kat1330 Aug 23 '19 at 18:48
1
var responseTask = System.Threading.Tasks.Task.FromResult(IdentityResult.Success);

_mocAuthService.Stub(s => s.RegisterUser(null)).IgnoreArguments().Return(responseTask);

If you need a successful IdentityResult then all you need to do is call the Success property. This will give you a successful IdentityResult.

https://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.identityresult(v=vs.108).aspx

kingkeamo
  • 274
  • 2
  • 6