1 // Copyright (c) .NET Foundation. All rights reserved.
2 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Security.Claims;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Microsoft.AspNetCore.Http;
11 using Microsoft.Extensions.Configuration;
12 using Microsoft.Extensions.DependencyInjection;
13 using Moq;
14 using Xunit;
15 
16 namespace Microsoft.AspNetCore.Identity.Test
17 {
18     public class UserManagerTest
19     {
20         [Fact]
EnsureDefaultServicesDefaultsWithStoreWorks()21         public void EnsureDefaultServicesDefaultsWithStoreWorks()
22         {
23             var config = new ConfigurationBuilder().Build();
24             var services = new ServiceCollection()
25                     .AddSingleton<IConfiguration>(config)
26                     .AddTransient<IUserStore<PocoUser>, NoopUserStore>();
27             services.AddIdentity<PocoUser, PocoRole>();
28             services.AddHttpContextAccessor();
29             services.AddLogging();
30             var manager = services.BuildServiceProvider().GetRequiredService<UserManager<PocoUser>>();
31             Assert.NotNull(manager.PasswordHasher);
32             Assert.NotNull(manager.Options);
33         }
34 
35         [Fact]
AddUserManagerWithCustomManagerReturnsSameInstance()36         public void AddUserManagerWithCustomManagerReturnsSameInstance()
37         {
38             var config = new ConfigurationBuilder().Build();
39             var services = new ServiceCollection()
40                     .AddSingleton<IConfiguration>(config)
41                     .AddTransient<IUserStore<PocoUser>, NoopUserStore>()
42                     .AddHttpContextAccessor();
43 
44             services.AddLogging();
45 
46             services.AddIdentity<PocoUser, PocoRole>()
47                 .AddUserManager<CustomUserManager>()
48                 .AddRoleManager<CustomRoleManager>();
49             var provider = services.BuildServiceProvider();
50             Assert.Same(provider.GetRequiredService<UserManager<PocoUser>>(),
51                 provider.GetRequiredService<CustomUserManager>());
52             Assert.Same(provider.GetRequiredService<RoleManager<PocoRole>>(),
53                 provider.GetRequiredService<CustomRoleManager>());
54         }
55 
56         public class CustomUserManager : UserManager<PocoUser>
57         {
CustomUserManager()58             public CustomUserManager() : base(new Mock<IUserStore<PocoUser>>().Object, null, null, null, null, null, null, null, null)
59             { }
60         }
61 
62         public class CustomRoleManager : RoleManager<PocoRole>
63         {
CustomRoleManager()64             public CustomRoleManager() : base(new Mock<IRoleStore<PocoRole>>().Object, null, null, null, null)
65             { }
66         }
67 
68         [Fact]
CreateCallsStore()69         public async Task CreateCallsStore()
70         {
71             // Setup
72             var store = new Mock<IUserStore<PocoUser>>();
73             var user = new PocoUser { UserName = "Foo" };
74             store.Setup(s => s.CreateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
75             store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
76             store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
77             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
78 
79             // Act
80             var result = await userManager.CreateAsync(user);
81 
82             // Assert
83             Assert.True(result.Succeeded);
84             store.VerifyAll();
85         }
86 
87         [Fact]
CreateCallsUpdateEmailStore()88         public async Task CreateCallsUpdateEmailStore()
89         {
90             // Setup
91             var store = new Mock<IUserEmailStore<PocoUser>>();
92             var user = new PocoUser { UserName = "Foo", Email = "Foo@foo.com" };
93             store.Setup(s => s.CreateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
94             store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
95             store.Setup(s => s.GetEmailAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.Email)).Verifiable();
96             store.Setup(s => s.SetNormalizedEmailAsync(user, user.Email.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
97             store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
98             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
99 
100             // Act
101             var result = await userManager.CreateAsync(user);
102 
103             // Assert
104             Assert.True(result.Succeeded);
105             store.VerifyAll();
106         }
107 
108         [Fact]
DeleteCallsStore()109         public async Task DeleteCallsStore()
110         {
111             // Setup
112             var store = new Mock<IUserStore<PocoUser>>();
113             var user = new PocoUser { UserName = "Foo" };
114             store.Setup(s => s.DeleteAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
115             var userManager = MockHelpers.TestUserManager(store.Object);
116 
117             // Act
118             var result = await userManager.DeleteAsync(user);
119 
120             // Assert
121             Assert.True(result.Succeeded);
122             store.VerifyAll();
123         }
124 
125         [Fact]
UpdateCallsStore()126         public async Task UpdateCallsStore()
127         {
128             // Setup
129             var store = new Mock<IUserStore<PocoUser>>();
130             var user = new PocoUser { UserName = "Foo" };
131             store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
132             store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
133             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
134             var userManager = MockHelpers.TestUserManager(store.Object);
135 
136             // Act
137             var result = await userManager.UpdateAsync(user);
138 
139             // Assert
140             Assert.True(result.Succeeded);
141             store.VerifyAll();
142         }
143 
144         [Fact]
UpdateWillUpdateNormalizedEmail()145         public async Task UpdateWillUpdateNormalizedEmail()
146         {
147             // Setup
148             var store = new Mock<IUserEmailStore<PocoUser>>();
149             var user = new PocoUser { UserName = "Foo", Email = "email" };
150             store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
151             store.Setup(s => s.GetEmailAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.Email)).Verifiable();
152             store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
153             store.Setup(s => s.SetNormalizedEmailAsync(user, user.Email.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
154             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
155             var userManager = MockHelpers.TestUserManager(store.Object);
156 
157             // Act
158             var result = await userManager.UpdateAsync(user);
159 
160             // Assert
161             Assert.True(result.Succeeded);
162             store.VerifyAll();
163         }
164 
165         [Fact]
SetUserNameCallsStore()166         public async Task SetUserNameCallsStore()
167         {
168             // Setup
169             var store = new Mock<IUserStore<PocoUser>>();
170             var user = new PocoUser();
171             store.Setup(s => s.SetUserNameAsync(user, "foo", CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
172             store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult("foo")).Verifiable();
173             store.Setup(s => s.SetNormalizedUserNameAsync(user, "FOO", CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
174             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
175             var userManager = MockHelpers.TestUserManager(store.Object);
176 
177             // Act
178             var result = await userManager.SetUserNameAsync(user, "foo");
179 
180             // Assert
181             Assert.True(result.Succeeded);
182             store.VerifyAll();
183         }
184 
185         [Fact]
FindByIdCallsStore()186         public async Task FindByIdCallsStore()
187         {
188             // Setup
189             var store = new Mock<IUserStore<PocoUser>>();
190             var user = new PocoUser { UserName = "Foo" };
191             store.Setup(s => s.FindByIdAsync(user.Id, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
192             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
193 
194             // Act
195             var result = await userManager.FindByIdAsync(user.Id);
196 
197             // Assert
198             Assert.Equal(user, result);
199             store.VerifyAll();
200         }
201 
202         [Fact]
FindByNameCallsStoreWithNormalizedName()203         public async Task FindByNameCallsStoreWithNormalizedName()
204         {
205             // Setup
206             var store = new Mock<IUserStore<PocoUser>>();
207             var user = new PocoUser { UserName = "Foo" };
208             store.Setup(s => s.FindByNameAsync(user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
209             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
210 
211             // Act
212             var result = await userManager.FindByNameAsync(user.UserName);
213 
214             // Assert
215             Assert.Equal(user, result);
216             store.VerifyAll();
217         }
218 
219         [Fact]
CanFindByNameCallsStoreWithoutNormalizedName()220         public async Task CanFindByNameCallsStoreWithoutNormalizedName()
221         {
222             // Setup
223             var store = new Mock<IUserStore<PocoUser>>();
224             var user = new PocoUser { UserName = "Foo" };
225             store.Setup(s => s.FindByNameAsync(user.UserName, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
226             var userManager = MockHelpers.TestUserManager(store.Object);
227             userManager.KeyNormalizer = null;
228 
229             // Act
230             var result = await userManager.FindByNameAsync(user.UserName);
231 
232             // Assert
233             Assert.Equal(user, result);
234             store.VerifyAll();
235         }
236 
237         [Fact]
FindByEmailCallsStoreWithNormalizedEmail()238         public async Task FindByEmailCallsStoreWithNormalizedEmail()
239         {
240             // Setup
241             var store = new Mock<IUserEmailStore<PocoUser>>();
242             var user = new PocoUser { Email = "Foo" };
243             store.Setup(s => s.FindByEmailAsync(user.Email.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
244             var userManager = MockHelpers.TestUserManager(store.Object);
245 
246             // Act
247             var result = await userManager.FindByEmailAsync(user.Email);
248 
249             // Assert
250             Assert.Equal(user, result);
251             store.VerifyAll();
252         }
253 
254         [Fact]
CanFindByEmailCallsStoreWithoutNormalizedEmail()255         public async Task CanFindByEmailCallsStoreWithoutNormalizedEmail()
256         {
257             // Setup
258             var store = new Mock<IUserEmailStore<PocoUser>>();
259             var user = new PocoUser { Email = "Foo" };
260             store.Setup(s => s.FindByEmailAsync(user.Email, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
261             var userManager = MockHelpers.TestUserManager(store.Object);
262             userManager.KeyNormalizer = null;
263 
264             // Act
265             var result = await userManager.FindByEmailAsync(user.Email);
266 
267             // Assert
268             Assert.Equal(user, result);
269             store.VerifyAll();
270         }
271 
272         [Fact]
AddToRolesCallsStore()273         public async Task AddToRolesCallsStore()
274         {
275             // Setup
276             var store = new Mock<IUserRoleStore<PocoUser>>();
277             var user = new PocoUser { UserName = "Foo" };
278             var roles = new string[] { "A", "B", "C", "C" };
279             store.Setup(s => s.AddToRoleAsync(user, "A", CancellationToken.None))
280                 .Returns(Task.FromResult(0))
281                 .Verifiable();
282             store.Setup(s => s.AddToRoleAsync(user, "B", CancellationToken.None))
283                 .Returns(Task.FromResult(0))
284                 .Verifiable();
285             store.Setup(s => s.AddToRoleAsync(user, "C", CancellationToken.None))
286                 .Returns(Task.FromResult(0))
287                 .Verifiable();
288 
289             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
290             store.Setup(s => s.IsInRoleAsync(user, "A", CancellationToken.None))
291                 .Returns(Task.FromResult(false))
292                 .Verifiable();
293             store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
294                 .Returns(Task.FromResult(false))
295                 .Verifiable();
296             store.Setup(s => s.IsInRoleAsync(user, "C", CancellationToken.None))
297                 .Returns(Task.FromResult(false))
298                 .Verifiable();
299             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
300 
301             // Act
302             var result = await userManager.AddToRolesAsync(user, roles);
303 
304             // Assert
305             Assert.True(result.Succeeded);
306             store.VerifyAll();
307             store.Verify(s => s.AddToRoleAsync(user, "C", CancellationToken.None), Times.Once());
308         }
309 
310         [Fact]
AddToRolesFailsIfUserInRole()311         public async Task AddToRolesFailsIfUserInRole()
312         {
313             // Setup
314             var store = new Mock<IUserRoleStore<PocoUser>>();
315             var user = new PocoUser { UserName = "Foo" };
316             var roles = new[] { "A", "B", "C" };
317             store.Setup(s => s.AddToRoleAsync(user, "A", CancellationToken.None))
318                 .Returns(Task.FromResult(0))
319                 .Verifiable();
320             store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
321                 .Returns(Task.FromResult(true))
322                 .Verifiable();
323             var userManager = MockHelpers.TestUserManager(store.Object);
324 
325             // Act
326             var result = await userManager.AddToRolesAsync(user, roles);
327 
328             // Assert
329             IdentityResultAssert.IsFailure(result, new IdentityErrorDescriber().UserAlreadyInRole("B"));
330             store.VerifyAll();
331         }
332 
333         [Fact]
RemoveFromRolesCallsStore()334         public async Task RemoveFromRolesCallsStore()
335         {
336             // Setup
337             var store = new Mock<IUserRoleStore<PocoUser>>();
338             var user = new PocoUser { UserName = "Foo" };
339             var roles = new[] { "A", "B", "C" };
340             store.Setup(s => s.RemoveFromRoleAsync(user, "A", CancellationToken.None))
341                 .Returns(Task.FromResult(0))
342                 .Verifiable();
343             store.Setup(s => s.RemoveFromRoleAsync(user, "B", CancellationToken.None))
344                 .Returns(Task.FromResult(0))
345                 .Verifiable();
346             store.Setup(s => s.RemoveFromRoleAsync(user, "C", CancellationToken.None))
347                 .Returns(Task.FromResult(0))
348                 .Verifiable();
349             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
350             store.Setup(s => s.IsInRoleAsync(user, "A", CancellationToken.None))
351                 .Returns(Task.FromResult(true))
352                 .Verifiable();
353             store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
354                 .Returns(Task.FromResult(true))
355                 .Verifiable();
356             store.Setup(s => s.IsInRoleAsync(user, "C", CancellationToken.None))
357                 .Returns(Task.FromResult(true))
358                 .Verifiable();
359             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
360 
361             // Act
362             var result = await userManager.RemoveFromRolesAsync(user, roles);
363 
364             // Assert
365             Assert.True(result.Succeeded);
366             store.VerifyAll();
367         }
368 
369         [Fact]
RemoveFromRolesFailsIfNotInRole()370         public async Task RemoveFromRolesFailsIfNotInRole()
371         {
372             // Setup
373             var store = new Mock<IUserRoleStore<PocoUser>>();
374             var user = new PocoUser { UserName = "Foo" };
375             var roles = new string[] { "A", "B", "C" };
376             store.Setup(s => s.RemoveFromRoleAsync(user, "A", CancellationToken.None))
377                 .Returns(Task.FromResult(0))
378                 .Verifiable();
379             store.Setup(s => s.IsInRoleAsync(user, "A", CancellationToken.None))
380                 .Returns(Task.FromResult(true))
381                 .Verifiable();
382             store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
383                 .Returns(Task.FromResult(false))
384                 .Verifiable();
385             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
386 
387             // Act
388             var result = await userManager.RemoveFromRolesAsync(user, roles);
389 
390             // Assert
391             IdentityResultAssert.IsFailure(result, new IdentityErrorDescriber().UserNotInRole("B"));
392             store.VerifyAll();
393         }
394 
395         [Fact]
AddClaimsCallsStore()396         public async Task AddClaimsCallsStore()
397         {
398             // Setup
399             var store = new Mock<IUserClaimStore<PocoUser>>();
400             var user = new PocoUser { UserName = "Foo" };
401             var claims = new Claim[] { new Claim("1", "1"), new Claim("2", "2"), new Claim("3", "3") };
402             store.Setup(s => s.AddClaimsAsync(user, claims, CancellationToken.None))
403                 .Returns(Task.FromResult(0))
404                 .Verifiable();
405             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
406             var userManager = MockHelpers.TestUserManager(store.Object);
407 
408             // Act
409             var result = await userManager.AddClaimsAsync(user, claims);
410 
411             // Assert
412             Assert.True(result.Succeeded);
413             store.VerifyAll();
414         }
415 
416         [Fact]
AddClaimCallsStore()417         public async Task AddClaimCallsStore()
418         {
419             // Setup
420             var store = new Mock<IUserClaimStore<PocoUser>>();
421             var user = new PocoUser { UserName = "Foo" };
422             var claim = new Claim("1", "1");
423             store.Setup(s => s.AddClaimsAsync(user, It.IsAny<IEnumerable<Claim>>(), CancellationToken.None))
424                 .Returns(Task.FromResult(0))
425                 .Verifiable();
426             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
427             var userManager = MockHelpers.TestUserManager(store.Object);
428 
429             // Act
430             var result = await userManager.AddClaimAsync(user, claim);
431 
432             // Assert
433             Assert.True(result.Succeeded);
434             store.VerifyAll();
435         }
436 
437         [Fact]
UpdateClaimCallsStore()438         public async Task UpdateClaimCallsStore()
439         {
440             // Setup
441             var store = new Mock<IUserClaimStore<PocoUser>>();
442             var user = new PocoUser { UserName = "Foo" };
443             var claim = new Claim("1", "1");
444             var newClaim = new Claim("1", "2");
445             store.Setup(s => s.ReplaceClaimAsync(user, It.IsAny<Claim>(), It.IsAny<Claim>(), CancellationToken.None))
446                 .Returns(Task.FromResult(0))
447                 .Verifiable();
448             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
449             var userManager = MockHelpers.TestUserManager(store.Object);
450 
451             // Act
452             var result = await userManager.ReplaceClaimAsync(user, claim, newClaim);
453 
454             // Assert
455             Assert.True(result.Succeeded);
456             store.VerifyAll();
457         }
458 
459         [Fact]
CheckPasswordWillRehashPasswordWhenNeeded()460         public async Task CheckPasswordWillRehashPasswordWhenNeeded()
461         {
462             // Setup
463             var store = new Mock<IUserPasswordStore<PocoUser>>();
464             var hasher = new Mock<IPasswordHasher<PocoUser>>();
465             var user = new PocoUser { UserName = "Foo" };
466             var pwd = "password";
467             var hashed = "hashed";
468             var rehashed = "rehashed";
469 
470             store.Setup(s => s.GetPasswordHashAsync(user, CancellationToken.None))
471                 .ReturnsAsync(hashed)
472                 .Verifiable();
473             store.Setup(s => s.SetPasswordHashAsync(user, It.IsAny<string>(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
474             store.Setup(x => x.UpdateAsync(It.IsAny<PocoUser>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(IdentityResult.Success));
475 
476             hasher.Setup(s => s.VerifyHashedPassword(user, hashed, pwd)).Returns(PasswordVerificationResult.SuccessRehashNeeded).Verifiable();
477             hasher.Setup(s => s.HashPassword(user, pwd)).Returns(rehashed).Verifiable();
478             var userManager = MockHelpers.TestUserManager(store.Object);
479             userManager.PasswordHasher = hasher.Object;
480 
481             // Act
482             var result = await userManager.CheckPasswordAsync(user, pwd);
483 
484             // Assert
485             Assert.True(result);
486             store.VerifyAll();
487             hasher.VerifyAll();
488         }
489 
490         [Fact]
CreateFailsWithNullSecurityStamp()491         public async Task CreateFailsWithNullSecurityStamp()
492         {
493             // Setup
494             var store = new Mock<IUserSecurityStampStore<PocoUser>>();
495             var manager = MockHelpers.TestUserManager(store.Object);
496             var user = new PocoUser { UserName = "nulldude" };
497             store.Setup(s => s.GetSecurityStampAsync(user, It.IsAny<CancellationToken>())).ReturnsAsync(default(string)).Verifiable();
498 
499             // Act
500             // Assert
501             var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => manager.CreateAsync(user));
502             Assert.Contains(Extensions.Identity.Core.Resources.NullSecurityStamp, ex.Message);
503 
504             store.VerifyAll();
505         }
506 
507         [Fact]
UpdateFailsWithNullSecurityStamp()508         public async Task UpdateFailsWithNullSecurityStamp()
509         {
510             // Setup
511             var store = new Mock<IUserSecurityStampStore<PocoUser>>();
512             var manager = MockHelpers.TestUserManager(store.Object);
513             var user = new PocoUser { UserName = "nulldude" };
514             store.Setup(s => s.GetSecurityStampAsync(user, It.IsAny<CancellationToken>())).ReturnsAsync(default(string)).Verifiable();
515 
516             // Act
517             // Assert
518             var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => manager.UpdateAsync(user));
519             Assert.Contains(Extensions.Identity.Core.Resources.NullSecurityStamp, ex.Message);
520 
521             store.VerifyAll();
522         }
523 
524 
525 
526         [Fact]
RemoveClaimsCallsStore()527         public async Task RemoveClaimsCallsStore()
528         {
529             // Setup
530             var store = new Mock<IUserClaimStore<PocoUser>>();
531             var user = new PocoUser { UserName = "Foo" };
532             var claims = new Claim[] { new Claim("1", "1"), new Claim("2", "2"), new Claim("3", "3") };
533             store.Setup(s => s.RemoveClaimsAsync(user, claims, CancellationToken.None))
534                 .Returns(Task.FromResult(0))
535                 .Verifiable();
536             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
537             var userManager = MockHelpers.TestUserManager(store.Object);
538 
539             // Act
540             var result = await userManager.RemoveClaimsAsync(user, claims);
541 
542             // Assert
543             Assert.True(result.Succeeded);
544             store.VerifyAll();
545         }
546 
547         [Fact]
RemoveClaimCallsStore()548         public async Task RemoveClaimCallsStore()
549         {
550             // Setup
551             var store = new Mock<IUserClaimStore<PocoUser>>();
552             var user = new PocoUser { UserName = "Foo" };
553             var claim = new Claim("1", "1");
554             store.Setup(s => s.RemoveClaimsAsync(user, It.IsAny<IEnumerable<Claim>>(), CancellationToken.None))
555                 .Returns(Task.FromResult(0))
556                 .Verifiable();
557             store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
558             var userManager = MockHelpers.TestUserManager<PocoUser>(store.Object);
559 
560             // Act
561             var result = await userManager.RemoveClaimAsync(user, claim);
562 
563             // Assert
564             Assert.True(result.Succeeded);
565             store.VerifyAll();
566         }
567 
568         [Fact]
CheckPasswordWithNullUserReturnsFalse()569         public async Task CheckPasswordWithNullUserReturnsFalse()
570         {
571             var manager = MockHelpers.TestUserManager(new EmptyStore());
572             Assert.False(await manager.CheckPasswordAsync(null, "whatevs"));
573         }
574 
575         [Fact]
UsersQueryableFailWhenStoreNotImplemented()576         public void UsersQueryableFailWhenStoreNotImplemented()
577         {
578             var manager = MockHelpers.TestUserManager(new NoopUserStore());
579             Assert.False(manager.SupportsQueryableUsers);
580             Assert.Throws<NotSupportedException>(() => manager.Users.Count());
581         }
582 
583         [Fact]
UsersEmailMethodsFailWhenStoreNotImplemented()584         public async Task UsersEmailMethodsFailWhenStoreNotImplemented()
585         {
586             var manager = MockHelpers.TestUserManager(new NoopUserStore());
587             Assert.False(manager.SupportsUserEmail);
588             await Assert.ThrowsAsync<NotSupportedException>(() => manager.FindByEmailAsync(null));
589             await Assert.ThrowsAsync<NotSupportedException>(() => manager.SetEmailAsync(null, null));
590             await Assert.ThrowsAsync<NotSupportedException>(() => manager.GetEmailAsync(null));
591             await Assert.ThrowsAsync<NotSupportedException>(() => manager.IsEmailConfirmedAsync(null));
592             await Assert.ThrowsAsync<NotSupportedException>(() => manager.ConfirmEmailAsync(null, null));
593         }
594 
595         [Fact]
UsersPhoneNumberMethodsFailWhenStoreNotImplemented()596         public async Task UsersPhoneNumberMethodsFailWhenStoreNotImplemented()
597         {
598             var manager = MockHelpers.TestUserManager(new NoopUserStore());
599             Assert.False(manager.SupportsUserPhoneNumber);
600             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetPhoneNumberAsync(null, null));
601             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetPhoneNumberAsync(null, null));
602             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetPhoneNumberAsync(null));
603         }
604 
605         [Fact]
TokenMethodsThrowWithNoTokenProvider()606         public async Task TokenMethodsThrowWithNoTokenProvider()
607         {
608             var manager = MockHelpers.TestUserManager(new NoopUserStore());
609             var user = new PocoUser();
610             await Assert.ThrowsAsync<NotSupportedException>(
611                 async () => await manager.GenerateUserTokenAsync(user, "bogus", null));
612             await Assert.ThrowsAsync<NotSupportedException>(
613                 async () => await manager.VerifyUserTokenAsync(user, "bogus", null, null));
614         }
615 
616         [Fact]
PasswordMethodsFailWhenStoreNotImplemented()617         public async Task PasswordMethodsFailWhenStoreNotImplemented()
618         {
619             var manager = MockHelpers.TestUserManager(new NoopUserStore());
620             Assert.False(manager.SupportsUserPassword);
621             await Assert.ThrowsAsync<NotSupportedException>(() => manager.CreateAsync(null, null));
622             await Assert.ThrowsAsync<NotSupportedException>(() => manager.ChangePasswordAsync(null, null, null));
623             await Assert.ThrowsAsync<NotSupportedException>(() => manager.AddPasswordAsync(null, null));
624             await Assert.ThrowsAsync<NotSupportedException>(() => manager.RemovePasswordAsync(null));
625             await Assert.ThrowsAsync<NotSupportedException>(() => manager.CheckPasswordAsync(null, null));
626             await Assert.ThrowsAsync<NotSupportedException>(() => manager.HasPasswordAsync(null));
627         }
628 
629         [Fact]
SecurityStampMethodsFailWhenStoreNotImplemented()630         public async Task SecurityStampMethodsFailWhenStoreNotImplemented()
631         {
632             var store = new Mock<IUserStore<PocoUser>>();
633             store.Setup(x => x.GetUserIdAsync(It.IsAny<PocoUser>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Guid.NewGuid().ToString()));
634             var manager = MockHelpers.TestUserManager(store.Object);
635             Assert.False(manager.SupportsUserSecurityStamp);
636             await Assert.ThrowsAsync<NotSupportedException>(() => manager.UpdateSecurityStampAsync(null));
637             await Assert.ThrowsAsync<NotSupportedException>(() => manager.GetSecurityStampAsync(null));
638             await Assert.ThrowsAsync<NotSupportedException>(
639                     () => manager.VerifyChangePhoneNumberTokenAsync(new PocoUser(), "1", "111-111-1111"));
640             await Assert.ThrowsAsync<NotSupportedException>(
641                     () => manager.GenerateChangePhoneNumberTokenAsync(new PocoUser(), "111-111-1111"));
642         }
643 
644         [Fact]
LoginMethodsFailWhenStoreNotImplemented()645         public async Task LoginMethodsFailWhenStoreNotImplemented()
646         {
647             var manager = MockHelpers.TestUserManager(new NoopUserStore());
648             Assert.False(manager.SupportsUserLogin);
649             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddLoginAsync(null, null));
650             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveLoginAsync(null, null, null));
651             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetLoginsAsync(null));
652             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.FindByLoginAsync(null, null));
653         }
654 
655         [Fact]
ClaimMethodsFailWhenStoreNotImplemented()656         public async Task ClaimMethodsFailWhenStoreNotImplemented()
657         {
658             var manager = MockHelpers.TestUserManager(new NoopUserStore());
659             Assert.False(manager.SupportsUserClaim);
660             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddClaimAsync(null, null));
661             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.ReplaceClaimAsync(null, null, null));
662             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveClaimAsync(null, null));
663             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetClaimsAsync(null));
664         }
665 
666         private class ATokenProvider : IUserTwoFactorTokenProvider<PocoUser>
667         {
CanGenerateTwoFactorTokenAsync(UserManager<PocoUser> manager, PocoUser user)668             public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<PocoUser> manager, PocoUser user)
669             {
670                 throw new NotImplementedException();
671             }
672 
GenerateAsync(string purpose, UserManager<PocoUser> manager, PocoUser user)673             public Task<string> GenerateAsync(string purpose, UserManager<PocoUser> manager, PocoUser user)
674             {
675                 throw new NotImplementedException();
676             }
677 
ValidateAsync(string purpose, string token, UserManager<PocoUser> manager, PocoUser user)678             public Task<bool> ValidateAsync(string purpose, string token, UserManager<PocoUser> manager, PocoUser user)
679             {
680                 throw new NotImplementedException();
681             }
682         }
683 
684         [Fact]
UserManagerWillUseTokenProviderInstance()685         public void UserManagerWillUseTokenProviderInstance()
686         {
687             var provider = new ATokenProvider();
688             var config = new ConfigurationBuilder().Build();
689             var services = new ServiceCollection()
690                     .AddSingleton<IConfiguration>(config)
691                     .AddLogging();
692 
693             services.AddIdentity<PocoUser, PocoRole>(o => o.Tokens.ProviderMap.Add("A", new TokenProviderDescriptor(typeof(ATokenProvider))
694             {
695                 ProviderInstance = provider
696             })).AddUserStore<NoopUserStore>();
697             var manager = services.BuildServiceProvider().GetService<UserManager<PocoUser>>();
698             Assert.ThrowsAsync<NotImplementedException>(() => manager.GenerateUserTokenAsync(new PocoUser(), "A", "purpose"));
699         }
700 
701         [Fact]
UserManagerThrowsIfStoreDoesNotSupportProtection()702         public void UserManagerThrowsIfStoreDoesNotSupportProtection()
703         {
704             var services = new ServiceCollection()
705                     .AddLogging();
706             services.AddIdentity<PocoUser, PocoRole>(o => o.Stores.ProtectPersonalData = true)
707                 .AddUserStore<NoopUserStore>();
708             var e = Assert.Throws<InvalidOperationException>(() => services.BuildServiceProvider().GetService<UserManager<PocoUser>>());
709             Assert.Contains("Store does not implement IProtectedUserStore", e.Message);
710         }
711 
712         [Fact]
UserManagerThrowsIfMissingPersonalDataProtection()713         public void UserManagerThrowsIfMissingPersonalDataProtection()
714         {
715             var services = new ServiceCollection()
716                     .AddLogging();
717             services.AddIdentity<PocoUser, PocoRole>(o => o.Stores.ProtectPersonalData = true)
718                 .AddUserStore<ProtectedStore>();
719             var e = Assert.Throws<InvalidOperationException>(() => services.BuildServiceProvider().GetService<UserManager<PocoUser>>());
720             Assert.Contains("No IPersonalDataProtector service was registered", e.Message);
721         }
722 
723         private class ProtectedStore : IProtectedUserStore<PocoUser>
724         {
CreateAsync(PocoUser user, CancellationToken cancellationToken)725             public Task<IdentityResult> CreateAsync(PocoUser user, CancellationToken cancellationToken)
726             {
727                 throw new NotImplementedException();
728             }
729 
DeleteAsync(PocoUser user, CancellationToken cancellationToken)730             public Task<IdentityResult> DeleteAsync(PocoUser user, CancellationToken cancellationToken)
731             {
732                 throw new NotImplementedException();
733             }
734 
Dispose()735             public void Dispose()
736             {
737                 throw new NotImplementedException();
738             }
739 
FindByIdAsync(string userId, CancellationToken cancellationToken)740             public Task<PocoUser> FindByIdAsync(string userId, CancellationToken cancellationToken)
741             {
742                 throw new NotImplementedException();
743             }
744 
FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)745             public Task<PocoUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
746             {
747                 throw new NotImplementedException();
748             }
749 
GetNormalizedUserNameAsync(PocoUser user, CancellationToken cancellationToken)750             public Task<string> GetNormalizedUserNameAsync(PocoUser user, CancellationToken cancellationToken)
751             {
752                 throw new NotImplementedException();
753             }
754 
GetUserIdAsync(PocoUser user, CancellationToken cancellationToken)755             public Task<string> GetUserIdAsync(PocoUser user, CancellationToken cancellationToken)
756             {
757                 throw new NotImplementedException();
758             }
759 
GetUserNameAsync(PocoUser user, CancellationToken cancellationToken)760             public Task<string> GetUserNameAsync(PocoUser user, CancellationToken cancellationToken)
761             {
762                 throw new NotImplementedException();
763             }
764 
SetNormalizedUserNameAsync(PocoUser user, string normalizedName, CancellationToken cancellationToken)765             public Task SetNormalizedUserNameAsync(PocoUser user, string normalizedName, CancellationToken cancellationToken)
766             {
767                 throw new NotImplementedException();
768             }
769 
SetUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken)770             public Task SetUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken)
771             {
772                 throw new NotImplementedException();
773             }
774 
UpdateAsync(PocoUser user, CancellationToken cancellationToken)775             public Task<IdentityResult> UpdateAsync(PocoUser user, CancellationToken cancellationToken)
776             {
777                 throw new NotImplementedException();
778             }
779         }
780 
781         [Fact]
UserManagerWillUseTokenProviderInstanceOverDefaults()782         public void UserManagerWillUseTokenProviderInstanceOverDefaults()
783         {
784             var provider = new ATokenProvider();
785             var config = new ConfigurationBuilder().Build();
786             var services = new ServiceCollection()
787                     .AddSingleton<IConfiguration>(config)
788                     .AddLogging();
789 
790             services.AddIdentity<PocoUser, PocoRole>(o => o.Tokens.ProviderMap.Add(TokenOptions.DefaultProvider, new TokenProviderDescriptor(typeof(ATokenProvider))
791                 {
792                     ProviderInstance = provider
793                 })).AddUserStore<NoopUserStore>().AddDefaultTokenProviders();
794             var manager = services.BuildServiceProvider().GetService<UserManager<PocoUser>>();
795             Assert.ThrowsAsync<NotImplementedException>(() => manager.GenerateUserTokenAsync(new PocoUser(), TokenOptions.DefaultProvider, "purpose"));
796         }
797 
798         [Fact]
TwoFactorStoreMethodsFailWhenStoreNotImplemented()799         public async Task TwoFactorStoreMethodsFailWhenStoreNotImplemented()
800         {
801             var manager = MockHelpers.TestUserManager(new NoopUserStore());
802             Assert.False(manager.SupportsUserTwoFactor);
803             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetTwoFactorEnabledAsync(null));
804             await
805                 Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetTwoFactorEnabledAsync(null, true));
806         }
807 
808         [Fact]
LockoutStoreMethodsFailWhenStoreNotImplemented()809         public async Task LockoutStoreMethodsFailWhenStoreNotImplemented()
810         {
811             var manager = MockHelpers.TestUserManager(new NoopUserStore());
812             Assert.False(manager.SupportsUserLockout);
813             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetLockoutEnabledAsync(null));
814             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetLockoutEnabledAsync(null, true));
815             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AccessFailedAsync(null));
816             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.IsLockedOutAsync(null));
817             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.ResetAccessFailedCountAsync(null));
818             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetAccessFailedCountAsync(null));
819         }
820 
821         [Fact]
RoleMethodsFailWhenStoreNotImplemented()822         public async Task RoleMethodsFailWhenStoreNotImplemented()
823         {
824             var manager = MockHelpers.TestUserManager(new NoopUserStore());
825             Assert.False(manager.SupportsUserRole);
826             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddToRoleAsync(null, "bogus"));
827             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddToRolesAsync(null, null));
828             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetRolesAsync(null));
829             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveFromRoleAsync(null, "bogus"));
830             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveFromRolesAsync(null, null));
831             await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.IsInRoleAsync(null, "bogus"));
832         }
833 
834         [Fact]
AuthTokenMethodsFailWhenStoreNotImplemented()835         public async Task AuthTokenMethodsFailWhenStoreNotImplemented()
836         {
837             var error = Extensions.Identity.Core.Resources.StoreNotIUserAuthenticationTokenStore;
838             var manager = MockHelpers.TestUserManager(new NoopUserStore());
839             Assert.False(manager.SupportsUserAuthenticationTokens);
840             await VerifyException<NotSupportedException>(async () => await manager.GetAuthenticationTokenAsync(null, null, null), error);
841             await VerifyException<NotSupportedException>(async () => await manager.SetAuthenticationTokenAsync(null, null, null, null), error);
842             await VerifyException<NotSupportedException>(async () => await manager.RemoveAuthenticationTokenAsync(null, null, null), error);
843         }
844 
845         [Fact]
AuthenticatorMethodsFailWhenStoreNotImplemented()846         public async Task AuthenticatorMethodsFailWhenStoreNotImplemented()
847         {
848             var error = Extensions.Identity.Core.Resources.StoreNotIUserAuthenticatorKeyStore;
849             var manager = MockHelpers.TestUserManager(new NoopUserStore());
850             Assert.False(manager.SupportsUserAuthenticatorKey);
851             await VerifyException<NotSupportedException>(async () => await manager.GetAuthenticatorKeyAsync(null), error);
852             await VerifyException<NotSupportedException>(async () => await manager.ResetAuthenticatorKeyAsync(null), error);
853         }
854 
855         [Fact]
RecoveryMethodsFailWhenStoreNotImplemented()856         public async Task RecoveryMethodsFailWhenStoreNotImplemented()
857         {
858             var error = Extensions.Identity.Core.Resources.StoreNotIUserTwoFactorRecoveryCodeStore;
859             var manager = MockHelpers.TestUserManager(new NoopUserStore());
860             Assert.False(manager.SupportsUserTwoFactorRecoveryCodes);
861             await VerifyException<NotSupportedException>(async () => await manager.RedeemTwoFactorRecoveryCodeAsync(null, null), error);
862             await VerifyException<NotSupportedException>(async () => await manager.GenerateNewTwoFactorRecoveryCodesAsync(null, 10), error);
863         }
864 
865         private async Task VerifyException<TException>(Func<Task> code, string expectedMessage) where TException : Exception
866         {
867             var error = await Assert.ThrowsAsync<TException>(code);
868             Assert.Equal(expectedMessage, error.Message);
869         }
870 
871         [Fact]
DisposeAfterDisposeDoesNotThrow()872         public void DisposeAfterDisposeDoesNotThrow()
873         {
874             var manager = MockHelpers.TestUserManager(new NoopUserStore());
875             manager.Dispose();
876             manager.Dispose();
877         }
878 
879         [Fact]
PasswordValidatorBlocksCreate()880         public async Task PasswordValidatorBlocksCreate()
881         {
882             // TODO: Can switch to Mock eventually
883             var manager = MockHelpers.TestUserManager(new EmptyStore());
884             manager.PasswordValidators.Clear();
885             manager.PasswordValidators.Add(new BadPasswordValidator<PocoUser>());
886             IdentityResultAssert.IsFailure(await manager.CreateAsync(new PocoUser(), "password"),
887                 BadPasswordValidator<PocoUser>.ErrorMessage);
888         }
889 
890         [Fact]
ResetTokenCallNoopForTokenValueZero()891         public async Task ResetTokenCallNoopForTokenValueZero()
892         {
893             var user = new PocoUser() { UserName = Guid.NewGuid().ToString() };
894             var store = new Mock<IUserLockoutStore<PocoUser>>();
895             store.Setup(x => x.ResetAccessFailedCountAsync(user, It.IsAny<CancellationToken>())).Returns(() =>
896                {
897                    throw new Exception();
898                });
899             var manager = MockHelpers.TestUserManager(store.Object);
900 
901             IdentityResultAssert.IsSuccess(await manager.ResetAccessFailedCountAsync(user));
902         }
903 
904         [Fact]
ManagerPublicNullChecks()905         public async Task ManagerPublicNullChecks()
906         {
907             Assert.Throws<ArgumentNullException>("store",
908                 () => new UserManager<PocoUser>(null, null, null, null, null, null, null, null, null));
909 
910             var manager = MockHelpers.TestUserManager(new NotImplementedStore());
911 
912             await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await manager.CreateAsync(null));
913             await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await manager.CreateAsync(null, null));
914             await
915                 Assert.ThrowsAsync<ArgumentNullException>("password",
916                     async () => await manager.CreateAsync(new PocoUser(), null));
917             await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await manager.UpdateAsync(null));
918             await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await manager.DeleteAsync(null));
919             await Assert.ThrowsAsync<ArgumentNullException>("claim", async () => await manager.AddClaimAsync(null, null));
920             await Assert.ThrowsAsync<ArgumentNullException>("claim", async () => await manager.ReplaceClaimAsync(null, null, null));
921             await Assert.ThrowsAsync<ArgumentNullException>("claims", async () => await manager.AddClaimsAsync(null, null));
922             await Assert.ThrowsAsync<ArgumentNullException>("userName", async () => await manager.FindByNameAsync(null));
923             await Assert.ThrowsAsync<ArgumentNullException>("login", async () => await manager.AddLoginAsync(null, null));
924             await Assert.ThrowsAsync<ArgumentNullException>("loginProvider",
925                 async () => await manager.RemoveLoginAsync(null, null, null));
926             await Assert.ThrowsAsync<ArgumentNullException>("providerKey",
927                 async () => await manager.RemoveLoginAsync(null, "", null));
928             await Assert.ThrowsAsync<ArgumentNullException>("email", async () => await manager.FindByEmailAsync(null));
929             Assert.Throws<ArgumentNullException>("provider", () => manager.RegisterTokenProvider("whatever", null));
930             await Assert.ThrowsAsync<ArgumentNullException>("roles", async () => await manager.AddToRolesAsync(new PocoUser(), null));
931             await Assert.ThrowsAsync<ArgumentNullException>("roles", async () => await manager.RemoveFromRolesAsync(new PocoUser(), null));
932         }
933 
934         [Fact]
MethodsFailWithUnknownUserTest()935         public async Task MethodsFailWithUnknownUserTest()
936         {
937             var manager = MockHelpers.TestUserManager(new EmptyStore());
938             manager.RegisterTokenProvider("whatever", new NoOpTokenProvider());
939             await Assert.ThrowsAsync<ArgumentNullException>("user",
940                 async () => await manager.GetUserNameAsync(null));
941             await Assert.ThrowsAsync<ArgumentNullException>("user",
942                 async () => await manager.SetUserNameAsync(null, "bogus"));
943             await Assert.ThrowsAsync<ArgumentNullException>("user",
944                 async () => await manager.AddClaimAsync(null, new Claim("a", "b")));
945             await Assert.ThrowsAsync<ArgumentNullException>("user",
946                 async () => await manager.AddLoginAsync(null, new UserLoginInfo("", "", "")));
947             await Assert.ThrowsAsync<ArgumentNullException>("user",
948                 async () => await manager.AddPasswordAsync(null, null));
949             await Assert.ThrowsAsync<ArgumentNullException>("user",
950                 async () => await manager.AddToRoleAsync(null, null));
951             await Assert.ThrowsAsync<ArgumentNullException>("user",
952                 async () => await manager.AddToRolesAsync(null, null));
953             await Assert.ThrowsAsync<ArgumentNullException>("user",
954                 async () => await manager.ChangePasswordAsync(null, null, null));
955             await Assert.ThrowsAsync<ArgumentNullException>("user",
956                 async () => await manager.GetClaimsAsync(null));
957             await Assert.ThrowsAsync<ArgumentNullException>("user",
958                 async () => await manager.GetLoginsAsync(null));
959             await Assert.ThrowsAsync<ArgumentNullException>("user",
960                 async () => await manager.GetRolesAsync(null));
961             await Assert.ThrowsAsync<ArgumentNullException>("user",
962                 async () => await manager.IsInRoleAsync(null, null));
963             await Assert.ThrowsAsync<ArgumentNullException>("user",
964                 async () => await manager.RemoveClaimAsync(null, new Claim("a", "b")));
965             await Assert.ThrowsAsync<ArgumentNullException>("user",
966                 async () => await manager.RemoveLoginAsync(null, "", ""));
967             await Assert.ThrowsAsync<ArgumentNullException>("user",
968                 async () => await manager.RemovePasswordAsync(null));
969             await Assert.ThrowsAsync<ArgumentNullException>("user",
970                 async () => await manager.RemoveFromRoleAsync(null, null));
971             await Assert.ThrowsAsync<ArgumentNullException>("user",
972                 async () => await manager.RemoveFromRolesAsync(null, null));
973             await Assert.ThrowsAsync<ArgumentNullException>("user",
974                 async () => await manager.ReplaceClaimAsync(null, new Claim("a", "b"), new Claim("a", "c")));
975             await Assert.ThrowsAsync<ArgumentNullException>("user",
976                 async () => await manager.UpdateSecurityStampAsync(null));
977             await Assert.ThrowsAsync<ArgumentNullException>("user",
978                 async () => await manager.GetSecurityStampAsync(null));
979             await Assert.ThrowsAsync<ArgumentNullException>("user",
980                 async () => await manager.HasPasswordAsync(null));
981             await Assert.ThrowsAsync<ArgumentNullException>("user",
982                 async () => await manager.GeneratePasswordResetTokenAsync(null));
983             await Assert.ThrowsAsync<ArgumentNullException>("user",
984                 async () => await manager.ResetPasswordAsync(null, null, null));
985             await Assert.ThrowsAsync<ArgumentNullException>("user",
986                 async () => await manager.IsEmailConfirmedAsync(null));
987             await Assert.ThrowsAsync<ArgumentNullException>("user",
988                 async () => await manager.GenerateEmailConfirmationTokenAsync(null));
989             await Assert.ThrowsAsync<ArgumentNullException>("user",
990                 async () => await manager.ConfirmEmailAsync(null, null));
991             await Assert.ThrowsAsync<ArgumentNullException>("user",
992                 async () => await manager.GetEmailAsync(null));
993             await Assert.ThrowsAsync<ArgumentNullException>("user",
994                 async () => await manager.SetEmailAsync(null, null));
995             await Assert.ThrowsAsync<ArgumentNullException>("user",
996                 async () => await manager.IsPhoneNumberConfirmedAsync(null));
997             await Assert.ThrowsAsync<ArgumentNullException>("user",
998                 async () => await manager.ChangePhoneNumberAsync(null, null, null));
999             await Assert.ThrowsAsync<ArgumentNullException>("user",
1000                 async () => await manager.VerifyChangePhoneNumberTokenAsync(null, null, null));
1001             await Assert.ThrowsAsync<ArgumentNullException>("user",
1002                 async () => await manager.GetPhoneNumberAsync(null));
1003             await Assert.ThrowsAsync<ArgumentNullException>("user",
1004                 async () => await manager.SetPhoneNumberAsync(null, null));
1005             await Assert.ThrowsAsync<ArgumentNullException>("user",
1006                 async () => await manager.GetTwoFactorEnabledAsync(null));
1007             await Assert.ThrowsAsync<ArgumentNullException>("user",
1008                 async () => await manager.SetTwoFactorEnabledAsync(null, true));
1009             await Assert.ThrowsAsync<ArgumentNullException>("user",
1010                 async () => await manager.GenerateTwoFactorTokenAsync(null, null));
1011             await Assert.ThrowsAsync<ArgumentNullException>("user",
1012                 async () => await manager.VerifyTwoFactorTokenAsync(null, null, null));
1013             await Assert.ThrowsAsync<ArgumentNullException>("user",
1014                 async () => await manager.GetValidTwoFactorProvidersAsync(null));
1015             await Assert.ThrowsAsync<ArgumentNullException>("user",
1016                 async () => await manager.VerifyUserTokenAsync(null, null, null, null));
1017             await Assert.ThrowsAsync<ArgumentNullException>("user",
1018                 async () => await manager.AccessFailedAsync(null));
1019             await Assert.ThrowsAsync<ArgumentNullException>("user",
1020                 async () => await manager.ResetAccessFailedCountAsync(null));
1021             await Assert.ThrowsAsync<ArgumentNullException>("user",
1022                 async () => await manager.GetAccessFailedCountAsync(null));
1023             await Assert.ThrowsAsync<ArgumentNullException>("user",
1024                 async () => await manager.GetLockoutEnabledAsync(null));
1025             await Assert.ThrowsAsync<ArgumentNullException>("user",
1026                 async () => await manager.SetLockoutEnabledAsync(null, false));
1027             await Assert.ThrowsAsync<ArgumentNullException>("user",
1028                 async () => await manager.SetLockoutEndDateAsync(null, DateTimeOffset.UtcNow));
1029             await Assert.ThrowsAsync<ArgumentNullException>("user",
1030                 async () => await manager.GetLockoutEndDateAsync(null));
1031             await Assert.ThrowsAsync<ArgumentNullException>("user",
1032                 async () => await manager.IsLockedOutAsync(null));
1033         }
1034 
1035         [Fact]
MethodsThrowWhenDisposedTest()1036         public async Task MethodsThrowWhenDisposedTest()
1037         {
1038             var manager = MockHelpers.TestUserManager(new NoopUserStore());
1039             manager.Dispose();
1040             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddClaimAsync(null, null));
1041             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddClaimsAsync(null, null));
1042             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddLoginAsync(null, null));
1043             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddPasswordAsync(null, null));
1044             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddToRoleAsync(null, null));
1045             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddToRolesAsync(null, null));
1046             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ChangePasswordAsync(null, null, null));
1047             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GetClaimsAsync(null));
1048             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GetLoginsAsync(null));
1049             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GetRolesAsync(null));
1050             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.IsInRoleAsync(null, null));
1051             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.RemoveClaimAsync(null, null));
1052             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.RemoveClaimsAsync(null, null));
1053             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.RemoveLoginAsync(null, null, null));
1054             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.RemovePasswordAsync(null));
1055             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.RemoveFromRoleAsync(null, null));
1056             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.RemoveFromRolesAsync(null, null));
1057             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.FindByLoginAsync(null, null));
1058             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.FindByIdAsync(null));
1059             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.FindByNameAsync(null));
1060             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.CreateAsync(null));
1061             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.CreateAsync(null, null));
1062             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.UpdateAsync(null));
1063             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.DeleteAsync(null));
1064             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ReplaceClaimAsync(null, null, null));
1065             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.UpdateSecurityStampAsync(null));
1066             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GetSecurityStampAsync(null));
1067             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GeneratePasswordResetTokenAsync(null));
1068             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ResetPasswordAsync(null, null, null));
1069             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GenerateEmailConfirmationTokenAsync(null));
1070             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.IsEmailConfirmedAsync(null));
1071             await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ConfirmEmailAsync(null, null));
1072         }
1073 
1074         private class BadPasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class
1075         {
1076             public static readonly IdentityError ErrorMessage = new IdentityError { Description = "I'm Bad." };
1077 
ValidateAsync(UserManager<TUser> manager, TUser user, string password)1078             public Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user, string password)
1079             {
1080                 return Task.FromResult(IdentityResult.Failed(ErrorMessage));
1081             }
1082         }
1083 
1084         private class EmptyStore :
1085             IUserPasswordStore<PocoUser>,
1086             IUserClaimStore<PocoUser>,
1087             IUserLoginStore<PocoUser>,
1088             IUserEmailStore<PocoUser>,
1089             IUserPhoneNumberStore<PocoUser>,
1090             IUserLockoutStore<PocoUser>,
1091             IUserTwoFactorStore<PocoUser>,
1092             IUserRoleStore<PocoUser>,
1093             IUserSecurityStampStore<PocoUser>
1094         {
GetClaimsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1095             public Task<IList<Claim>> GetClaimsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1096             {
1097                 return Task.FromResult<IList<Claim>>(new List<Claim>());
1098             }
1099 
AddClaimsAsync(PocoUser user, IEnumerable<Claim> claim, CancellationToken cancellationToken = default(CancellationToken))1100             public Task AddClaimsAsync(PocoUser user, IEnumerable<Claim> claim, CancellationToken cancellationToken = default(CancellationToken))
1101             {
1102                 return Task.FromResult(0);
1103             }
1104 
ReplaceClaimAsync(PocoUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))1105             public Task ReplaceClaimAsync(PocoUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
1106             {
1107                 return Task.FromResult(0);
1108             }
1109 
RemoveClaimsAsync(PocoUser user, IEnumerable<Claim> claim, CancellationToken cancellationToken = default(CancellationToken))1110             public Task RemoveClaimsAsync(PocoUser user, IEnumerable<Claim> claim, CancellationToken cancellationToken = default(CancellationToken))
1111             {
1112                 return Task.FromResult(0);
1113             }
1114 
SetEmailAsync(PocoUser user, string email, CancellationToken cancellationToken = default(CancellationToken))1115             public Task SetEmailAsync(PocoUser user, string email, CancellationToken cancellationToken = default(CancellationToken))
1116             {
1117                 return Task.FromResult(0);
1118             }
1119 
GetEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1120             public Task<string> GetEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1121             {
1122                 return Task.FromResult("");
1123             }
1124 
GetEmailConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1125             public Task<bool> GetEmailConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1126             {
1127                 return Task.FromResult(false);
1128             }
1129 
SetEmailConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))1130             public Task SetEmailConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
1131             {
1132                 return Task.FromResult(0);
1133             }
1134 
FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))1135             public Task<PocoUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))
1136             {
1137                 return Task.FromResult<PocoUser>(null);
1138             }
1139 
GetLockoutEndDateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1140             public Task<DateTimeOffset?> GetLockoutEndDateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1141             {
1142                 return Task.FromResult<DateTimeOffset?>(DateTimeOffset.MinValue);
1143             }
1144 
SetLockoutEndDateAsync(PocoUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))1145             public Task SetLockoutEndDateAsync(PocoUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))
1146             {
1147                 return Task.FromResult(0);
1148             }
1149 
IncrementAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1150             public Task<int> IncrementAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1151             {
1152                 return Task.FromResult(0);
1153             }
1154 
ResetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1155             public Task ResetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1156             {
1157                 return Task.FromResult(0);
1158             }
1159 
GetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1160             public Task<int> GetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1161             {
1162                 return Task.FromResult(0);
1163             }
1164 
GetLockoutEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1165             public Task<bool> GetLockoutEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1166             {
1167                 return Task.FromResult(false);
1168             }
1169 
SetLockoutEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))1170             public Task SetLockoutEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
1171             {
1172                 return Task.FromResult(0);
1173             }
1174 
AddLoginAsync(PocoUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken))1175             public Task AddLoginAsync(PocoUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken))
1176             {
1177                 return Task.FromResult(0);
1178             }
1179 
RemoveLoginAsync(PocoUser user, string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))1180             public Task RemoveLoginAsync(PocoUser user, string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
1181             {
1182                 return Task.FromResult(0);
1183             }
1184 
GetLoginsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1185             public Task<IList<UserLoginInfo>> GetLoginsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1186             {
1187                 return Task.FromResult<IList<UserLoginInfo>>(new List<UserLoginInfo>());
1188             }
1189 
FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))1190             public Task<PocoUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
1191             {
1192                 return Task.FromResult<PocoUser>(null);
1193             }
1194 
Dispose()1195             public void Dispose()
1196             {
1197             }
1198 
SetUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))1199             public Task SetUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
1200             {
1201                 return Task.FromResult(0);
1202             }
1203 
CreateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1204             public Task<IdentityResult> CreateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1205             {
1206                 return Task.FromResult(IdentityResult.Success);
1207             }
1208 
UpdateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1209             public Task<IdentityResult> UpdateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1210             {
1211                 return Task.FromResult(IdentityResult.Success);
1212             }
1213 
DeleteAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1214             public Task<IdentityResult> DeleteAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1215             {
1216                 return Task.FromResult(IdentityResult.Success);
1217             }
1218 
FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))1219             public Task<PocoUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
1220             {
1221                 return Task.FromResult<PocoUser>(null);
1222             }
1223 
FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))1224             public Task<PocoUser> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))
1225             {
1226                 return Task.FromResult<PocoUser>(null);
1227             }
1228 
SetPasswordHashAsync(PocoUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))1229             public Task SetPasswordHashAsync(PocoUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
1230             {
1231                 return Task.FromResult(0);
1232             }
1233 
GetPasswordHashAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1234             public Task<string> GetPasswordHashAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1235             {
1236                 return Task.FromResult<string>(null);
1237             }
1238 
HasPasswordAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1239             public Task<bool> HasPasswordAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1240             {
1241                 return Task.FromResult(false);
1242             }
1243 
SetPhoneNumberAsync(PocoUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))1244             public Task SetPhoneNumberAsync(PocoUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))
1245             {
1246                 return Task.FromResult(0);
1247             }
1248 
GetPhoneNumberAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1249             public Task<string> GetPhoneNumberAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1250             {
1251                 return Task.FromResult("");
1252             }
1253 
GetPhoneNumberConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1254             public Task<bool> GetPhoneNumberConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1255             {
1256                 return Task.FromResult(false);
1257             }
1258 
SetPhoneNumberConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))1259             public Task SetPhoneNumberConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
1260             {
1261                 return Task.FromResult(0);
1262             }
1263 
AddToRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))1264             public Task AddToRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
1265             {
1266                 return Task.FromResult(0);
1267             }
1268 
RemoveFromRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))1269             public Task RemoveFromRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
1270             {
1271                 return Task.FromResult(0);
1272             }
1273 
GetRolesAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1274             public Task<IList<string>> GetRolesAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1275             {
1276                 return Task.FromResult<IList<string>>(new List<string>());
1277             }
1278 
IsInRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))1279             public Task<bool> IsInRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
1280             {
1281                 return Task.FromResult(false);
1282             }
1283 
SetSecurityStampAsync(PocoUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken))1284             public Task SetSecurityStampAsync(PocoUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken))
1285             {
1286                 return Task.FromResult(0);
1287             }
1288 
GetSecurityStampAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1289             public Task<string> GetSecurityStampAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1290             {
1291                 return Task.FromResult("");
1292             }
1293 
SetTwoFactorEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))1294             public Task SetTwoFactorEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
1295             {
1296                 return Task.FromResult(0);
1297             }
1298 
GetTwoFactorEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1299             public Task<bool> GetTwoFactorEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1300             {
1301                 return Task.FromResult(false);
1302             }
1303 
GetUserIdAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1304             public Task<string> GetUserIdAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1305             {
1306                 return Task.FromResult<string>(null);
1307             }
1308 
GetUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1309             public Task<string> GetUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1310             {
1311                 return Task.FromResult<string>(null);
1312             }
1313 
GetNormalizedUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1314             public Task<string> GetNormalizedUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1315             {
1316                 return Task.FromResult<string>(null);
1317             }
1318 
SetNormalizedUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))1319             public Task SetNormalizedUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
1320             {
1321                 return Task.FromResult(0);
1322             }
1323 
GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))1324             public Task<IList<PocoUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
1325             {
1326                 return Task.FromResult<IList<PocoUser>>(new List<PocoUser>());
1327             }
1328 
GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))1329             public Task<IList<PocoUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
1330             {
1331                 return Task.FromResult<IList<PocoUser>>(new List<PocoUser>());
1332             }
1333 
GetNormalizedEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1334             public Task<string> GetNormalizedEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1335             {
1336                 return Task.FromResult("");
1337             }
1338 
SetNormalizedEmailAsync(PocoUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))1339             public Task SetNormalizedEmailAsync(PocoUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
1340             {
1341                 return Task.FromResult(0);
1342             }
1343         }
1344 
1345         private class NoOpTokenProvider : IUserTwoFactorTokenProvider<PocoUser>
1346         {
1347             public string Name { get; } = "Noop";
1348 
GenerateAsync(string purpose, UserManager<PocoUser> manager, PocoUser user)1349             public Task<string> GenerateAsync(string purpose, UserManager<PocoUser> manager, PocoUser user)
1350             {
1351                 return Task.FromResult("Test");
1352             }
1353 
ValidateAsync(string purpose, string token, UserManager<PocoUser> manager, PocoUser user)1354             public Task<bool> ValidateAsync(string purpose, string token, UserManager<PocoUser> manager, PocoUser user)
1355             {
1356                 return Task.FromResult(true);
1357             }
1358 
CanGenerateTwoFactorTokenAsync(UserManager<PocoUser> manager, PocoUser user)1359             public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<PocoUser> manager, PocoUser user)
1360             {
1361                 return Task.FromResult(true);
1362             }
1363         }
1364 
1365         private class NotImplementedStore :
1366             IUserPasswordStore<PocoUser>,
1367             IUserClaimStore<PocoUser>,
1368             IUserLoginStore<PocoUser>,
1369             IUserRoleStore<PocoUser>,
1370             IUserEmailStore<PocoUser>,
1371             IUserPhoneNumberStore<PocoUser>,
1372             IUserLockoutStore<PocoUser>,
1373             IUserTwoFactorStore<PocoUser>
1374         {
GetClaimsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1375             public Task<IList<Claim>> GetClaimsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1376             {
1377                 throw new NotImplementedException();
1378             }
1379 
AddClaimsAsync(PocoUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))1380             public Task AddClaimsAsync(PocoUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
1381             {
1382                 throw new NotImplementedException();
1383             }
1384 
ReplaceClaimAsync(PocoUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))1385             public Task ReplaceClaimAsync(PocoUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
1386             {
1387                 throw new NotImplementedException();
1388             }
1389 
RemoveClaimsAsync(PocoUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))1390             public Task RemoveClaimsAsync(PocoUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
1391             {
1392                 throw new NotImplementedException();
1393             }
1394 
SetEmailAsync(PocoUser user, string email, CancellationToken cancellationToken = default(CancellationToken))1395             public Task SetEmailAsync(PocoUser user, string email, CancellationToken cancellationToken = default(CancellationToken))
1396             {
1397                 throw new NotImplementedException();
1398             }
1399 
GetEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1400             public Task<string> GetEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1401             {
1402                 throw new NotImplementedException();
1403             }
1404 
GetEmailConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1405             public Task<bool> GetEmailConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1406             {
1407                 throw new NotImplementedException();
1408             }
1409 
SetEmailConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))1410             public Task SetEmailConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
1411             {
1412                 throw new NotImplementedException();
1413             }
1414 
FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))1415             public Task<PocoUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))
1416             {
1417                 throw new NotImplementedException();
1418             }
1419 
GetLockoutEndDateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1420             public Task<DateTimeOffset?> GetLockoutEndDateAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1421             {
1422                 throw new NotImplementedException();
1423             }
1424 
SetLockoutEndDateAsync(PocoUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))1425             public Task SetLockoutEndDateAsync(PocoUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))
1426             {
1427                 throw new NotImplementedException();
1428             }
1429 
IncrementAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1430             public Task<int> IncrementAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1431             {
1432                 throw new NotImplementedException();
1433             }
1434 
ResetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1435             public Task ResetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1436             {
1437                 throw new NotImplementedException();
1438             }
1439 
GetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1440             public Task<int> GetAccessFailedCountAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1441             {
1442                 throw new NotImplementedException();
1443             }
1444 
GetLockoutEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1445             public Task<bool> GetLockoutEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1446             {
1447                 throw new NotImplementedException();
1448             }
1449 
SetLockoutEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))1450             public Task SetLockoutEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
1451             {
1452                 throw new NotImplementedException();
1453             }
1454 
AddLoginAsync(PocoUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken))1455             public Task AddLoginAsync(PocoUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken))
1456             {
1457                 throw new NotImplementedException();
1458             }
1459 
RemoveLoginAsync(PocoUser user, string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))1460             public Task RemoveLoginAsync(PocoUser user, string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
1461             {
1462                 throw new NotImplementedException();
1463             }
1464 
GetLoginsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1465             public Task<IList<UserLoginInfo>> GetLoginsAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1466             {
1467                 throw new NotImplementedException();
1468             }
1469 
FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))1470             public Task<PocoUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
1471             {
1472                 throw new NotImplementedException();
1473             }
1474 
Dispose()1475             public void Dispose()
1476             {
1477                 throw new NotImplementedException();
1478             }
1479 
GetUserIdAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1480             public Task<string> GetUserIdAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1481             {
1482                 throw new NotImplementedException();
1483             }
1484 
GetUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1485             public Task<string> GetUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1486             {
1487                 throw new NotImplementedException();
1488             }
1489 
SetUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))1490             public Task SetUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
1491             {
1492                 throw new NotImplementedException();
1493             }
1494 
FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))1495             public Task<PocoUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
1496             {
1497                 throw new NotImplementedException();
1498             }
1499 
FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))1500             public Task<PocoUser> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))
1501             {
1502                 throw new NotImplementedException();
1503             }
1504 
SetPasswordHashAsync(PocoUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))1505             public Task SetPasswordHashAsync(PocoUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
1506             {
1507                 throw new NotImplementedException();
1508             }
1509 
GetPasswordHashAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1510             public Task<string> GetPasswordHashAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1511             {
1512                 throw new NotImplementedException();
1513             }
1514 
HasPasswordAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1515             public Task<bool> HasPasswordAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1516             {
1517                 throw new NotImplementedException();
1518             }
1519 
SetPhoneNumberAsync(PocoUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))1520             public Task SetPhoneNumberAsync(PocoUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))
1521             {
1522                 throw new NotImplementedException();
1523             }
1524 
GetPhoneNumberAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1525             public Task<string> GetPhoneNumberAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1526             {
1527                 throw new NotImplementedException();
1528             }
1529 
GetPhoneNumberConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1530             public Task<bool> GetPhoneNumberConfirmedAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1531             {
1532                 throw new NotImplementedException();
1533             }
1534 
SetPhoneNumberConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))1535             public Task SetPhoneNumberConfirmedAsync(PocoUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
1536             {
1537                 throw new NotImplementedException();
1538             }
1539 
SetTwoFactorEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))1540             public Task SetTwoFactorEnabledAsync(PocoUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
1541             {
1542                 throw new NotImplementedException();
1543             }
1544 
GetTwoFactorEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1545             public Task<bool> GetTwoFactorEnabledAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1546             {
1547                 throw new NotImplementedException();
1548             }
1549 
AddToRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))1550             public Task AddToRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
1551             {
1552                 throw new NotImplementedException();
1553             }
1554 
RemoveFromRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))1555             public Task RemoveFromRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
1556             {
1557                 throw new NotImplementedException();
1558             }
1559 
GetRolesAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1560             public Task<IList<string>> GetRolesAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1561             {
1562                 throw new NotImplementedException();
1563             }
1564 
IsInRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))1565             public Task<bool> IsInRoleAsync(PocoUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
1566             {
1567                 throw new NotImplementedException();
1568             }
1569 
GetNormalizedUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1570             public Task<string> GetNormalizedUserNameAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1571             {
1572                 throw new NotImplementedException();
1573             }
1574 
SetNormalizedUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))1575             public Task SetNormalizedUserNameAsync(PocoUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
1576             {
1577                 throw new NotImplementedException();
1578             }
1579 
GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))1580             public Task<IList<PocoUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
1581             {
1582                 throw new NotImplementedException();
1583             }
1584 
GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))1585             public Task<IList<PocoUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
1586             {
1587                 throw new NotImplementedException();
1588             }
1589 
CreateAsync(PocoUser user, CancellationToken cancellationToken)1590             Task<IdentityResult> IUserStore<PocoUser>.CreateAsync(PocoUser user, CancellationToken cancellationToken)
1591             {
1592                 throw new NotImplementedException();
1593             }
1594 
UpdateAsync(PocoUser user, CancellationToken cancellationToken)1595             Task<IdentityResult> IUserStore<PocoUser>.UpdateAsync(PocoUser user, CancellationToken cancellationToken)
1596             {
1597                 throw new NotImplementedException();
1598             }
1599 
DeleteAsync(PocoUser user, CancellationToken cancellationToken)1600             Task<IdentityResult> IUserStore<PocoUser>.DeleteAsync(PocoUser user, CancellationToken cancellationToken)
1601             {
1602                 throw new NotImplementedException();
1603             }
1604 
GetNormalizedEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))1605             public Task<string> GetNormalizedEmailAsync(PocoUser user, CancellationToken cancellationToken = default(CancellationToken))
1606             {
1607                 throw new NotImplementedException();
1608             }
1609 
SetNormalizedEmailAsync(PocoUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))1610             public Task SetNormalizedEmailAsync(PocoUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
1611             {
1612                 throw new NotImplementedException();
1613             }
1614         }
1615 
1616         [Fact]
CanCustomizeUserValidatorErrors()1617         public async Task CanCustomizeUserValidatorErrors()
1618         {
1619             var store = new Mock<IUserEmailStore<PocoUser>>();
1620             var describer = new TestErrorDescriber();
1621             var config = new ConfigurationBuilder().Build();
1622             var services = new ServiceCollection()
1623                     .AddSingleton<IConfiguration>(config)
1624                     .AddLogging()
1625                     .AddSingleton<IdentityErrorDescriber>(describer)
1626                     .AddSingleton<IUserStore<PocoUser>>(store.Object)
1627                     .AddHttpContextAccessor();
1628 
1629             services.AddIdentity<PocoUser, PocoRole>();
1630 
1631             var manager = services.BuildServiceProvider().GetRequiredService<UserManager<PocoUser>>();
1632 
1633             manager.Options.User.RequireUniqueEmail = true;
1634             var user = new PocoUser() { UserName = "dupeEmail", Email = "dupe@email.com" };
1635             var user2 = new PocoUser() { UserName = "dupeEmail2", Email = "dupe@email.com" };
1636             store.Setup(s => s.FindByEmailAsync("DUPE@EMAIL.COM", CancellationToken.None))
1637                 .Returns(Task.FromResult(user2))
1638                 .Verifiable();
1639             store.Setup(s => s.GetUserIdAsync(user2, CancellationToken.None))
1640                 .Returns(Task.FromResult(user2.Id))
1641                 .Verifiable();
1642             store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None))
1643                 .Returns(Task.FromResult(user.UserName))
1644                 .Verifiable();
1645             store.Setup(s => s.GetEmailAsync(user, CancellationToken.None))
1646                 .Returns(Task.FromResult(user.Email))
1647                 .Verifiable();
1648 
1649             Assert.Same(describer, manager.ErrorDescriber);
1650             IdentityResultAssert.IsFailure(await manager.CreateAsync(user), describer.DuplicateEmail(user.Email));
1651 
1652             store.VerifyAll();
1653         }
1654 
1655         public class TestErrorDescriber : IdentityErrorDescriber
1656         {
1657             public static string Code = "Error";
1658             public static string FormatError = "FormatError {0}";
1659 
DuplicateEmail(string email)1660             public override IdentityError DuplicateEmail(string email)
1661             {
1662                 return new IdentityError { Code = Code, Description = string.Format(FormatError, email) };
1663             }
1664         }
1665 
1666     }
1667 }