diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/CustomPocoTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/CustomPocoTest.cs index 6938dacc61..2603c3654d 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/CustomPocoTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/CustomPocoTest.cs @@ -4,17 +4,20 @@ using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNet.Identity.Test; using Microsoft.AspNet.Testing.xunit; using Microsoft.Data.Entity; using Xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] - public class CustomPocoTest + public class CustomPocoTest : IClassFixture { - private readonly string ConnectionString = @"Server=(localdb)\mssqllocaldb;Database=CustomUserContextTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;Connection Timeout=30"; + private readonly ScratchDatabaseFixture _fixture; + + public CustomPocoTest(ScratchDatabaseFixture fixture) + { + _fixture = fixture; + } public class User where TKey : IEquatable { @@ -30,7 +33,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public CustomDbContext GetContext() where TKey : IEquatable { - return DbUtil.Create>(ConnectionString); + return DbUtil.Create>(_fixture.ConnectionString); } public CustomDbContext CreateContext(bool delete = false) where TKey : IEquatable @@ -44,30 +47,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test return db; } - [TestPriority(-1000)] [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] - public void DropDatabaseStart() - { - DropDb(); - } - - [TestPriority(10000)] - [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] - public void DropDatabaseDone() - { - DropDb(); - } - - public void DropDb() - { - var db = GetContext(); - db.Database.EnsureDeleted(); - } - - [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameGuid() { using (var db = CreateContext(true)) @@ -85,7 +68,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameString() { using (var db = CreateContext(true)) @@ -103,7 +88,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUserInt() { using (var db = CreateContext(true)) @@ -119,7 +106,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUserIntViaSet() { using (var db = CreateContext(true)) @@ -136,13 +125,15 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameInt() { using (var db = CreateContext(true)) { var oldName = Guid.NewGuid().ToString(); - var user = new User { UserName = oldName}; + var user = new User { UserName = oldName }; db.Users.Add(user); await db.SaveChangesAsync(); var newName = Guid.NewGuid().ToString(); @@ -154,13 +145,15 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)][OSSkipCondition(OperatingSystems.Linux)][OSSkipCondition(OperatingSystems.MacOSX)] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanUpdateNameIntWithSet() { using (var db = CreateContext(true)) { var oldName = Guid.NewGuid().ToString(); - var user = new User { UserName = oldName}; + var user = new User { UserName = oldName }; db.Set>().Add(user); await db.SaveChangesAsync(); var newName = Guid.NewGuid().ToString(); diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/DbUtil.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/DbUtil.cs index 482ff5acc3..3b50d018ca 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/DbUtil.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/DbUtil.cs @@ -9,7 +9,6 @@ using Xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] public static class DbUtil { public static IServiceCollection ConfigureDbServices(string connectionString, IServiceCollection services = null) @@ -28,16 +27,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test return services; } - public static IdentityDbContext Create(string connectionString) - { - return Create(connectionString); - } - public static TContext Create(string connectionString) where TContext : DbContext, new() { var serviceProvider = ConfigureDbServices(connectionString).BuildServiceProvider(); return serviceProvider.GetRequiredService(); } - } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/DefaultPocoTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/DefaultPocoTest.cs index 1aefc04aeb..5cf47290e2 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/DefaultPocoTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/DefaultPocoTest.cs @@ -7,56 +7,39 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNet.Builder.Internal; using Microsoft.AspNet.Identity.Test; +using Microsoft.AspNet.Testing.xunit; using Microsoft.Data.Entity; using Microsoft.Extensions.DependencyInjection; using Xunit; -using Microsoft.AspNet.Testing.xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] - public class DefaultPocoTest + public class DefaultPocoTest : IClassFixture { - private readonly string ConnectionString = @"Server=(localdb)\mssqllocaldb;Database=DefaultSchemaTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;MultipleActiveResultSets=true;Connection Timeout=30"; - public IdentityDbContext CreateContext(bool ensureCreated = false) + private readonly ApplicationBuilder _builder; + private const string DatabaseName = nameof(DefaultPocoTest); + + public DefaultPocoTest(ScratchDatabaseFixture fixture) { - var db = DbUtil.Create(ConnectionString); - if (ensureCreated) + var services = new ServiceCollection(); + + services + .AddLogging() + .AddEntityFramework() + .AddSqlServer() + .AddDbContext(o => o.UseSqlServer(fixture.ConnectionString)) + .ServiceCollection() + .AddIdentity() + .AddEntityFrameworkStores(); + + var provider = services.BuildServiceProvider(); + _builder = new ApplicationBuilder(provider); + + using(var scoped = provider.GetRequiredService().CreateScope()) + using (var db = scoped.ServiceProvider.GetRequiredService()) { db.Database.EnsureCreated(); } - return db; - } - - public void DropDb() - { - var db = CreateContext(); - db.Database.EnsureDeleted(); - } - - [TestPriority(-1000)] - [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] - public void DropDatabaseStart() - { - DropDb(); - } - - private IServiceProvider ConfigureServices() - { - var services = new ServiceCollection(); - DbUtil.ConfigureDbServices(ConnectionString, services); - services.AddLogging(); - services.AddIdentity().AddEntityFrameworkStores(); - return services.BuildServiceProvider(); - } - - private ApplicationBuilder CreateBuilder() - { - var builder = new ApplicationBuilder(ConfigureServices()); - return builder; } [ConditionalFact] @@ -65,11 +48,8 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test [OSSkipCondition(OperatingSystems.MacOSX)] public async Task EnsureStartupUsageWorks() { - var context = CreateContext(true); - var builder = CreateBuilder(); - - var userStore = builder.ApplicationServices.GetRequiredService>(); - var userManager = builder.ApplicationServices.GetRequiredService>(); + var userStore = _builder.ApplicationServices.GetRequiredService>(); + var userManager = _builder.ApplicationServices.GetRequiredService>(); Assert.NotNull(userStore); Assert.NotNull(userManager); @@ -88,11 +68,8 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public async Task CanIncludeUserClaimsTest() { // Arrange - CreateContext(true); - var builder = CreateBuilder(); - - var userManager = builder.ApplicationServices.GetRequiredService>(); - var dbContext = builder.ApplicationServices.GetRequiredService(); + var userManager = _builder.ApplicationServices.GetRequiredService>(); + var dbContext = _builder.ApplicationServices.GetRequiredService(); var username = "user" + new Random().Next(); var user = new IdentityUser() { UserName = username }; @@ -118,11 +95,8 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public async Task CanIncludeUserLoginsTest() { // Arrange - CreateContext(true); - var builder = CreateBuilder(); - - var userManager = builder.ApplicationServices.GetRequiredService>(); - var dbContext = builder.ApplicationServices.GetRequiredService(); + var userManager = _builder.ApplicationServices.GetRequiredService>(); + var dbContext = _builder.ApplicationServices.GetRequiredService(); var username = "user" + new Random().Next(); var user = new IdentityUser() { UserName = username }; @@ -148,12 +122,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public async Task CanIncludeUserRolesTest() { // Arrange - CreateContext(true); - var builder = CreateBuilder(); - - var userManager = builder.ApplicationServices.GetRequiredService>(); - var roleManager = builder.ApplicationServices.GetRequiredService>(); - var dbContext = builder.ApplicationServices.GetRequiredService(); + var userManager = _builder.ApplicationServices.GetRequiredService>(); + var roleManager = _builder.ApplicationServices.GetRequiredService>(); + var dbContext = _builder.ApplicationServices.GetRequiredService(); const string roleName = "Admin"; for (var i = 0; i < 10; i++) @@ -192,11 +163,8 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public async Task CanIncludeRoleClaimsTest() { // Arrange - CreateContext(true); - var builder = CreateBuilder(); - - var roleManager = builder.ApplicationServices.GetRequiredService>(); - var dbContext = builder.ApplicationServices.GetRequiredService(); + var roleManager = _builder.ApplicationServices.GetRequiredService>(); + var dbContext = _builder.ApplicationServices.GetRequiredService(); var role = new IdentityRole("Admin"); @@ -214,15 +182,5 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test Assert.NotNull(role.Claims); Assert.Equal(10, role.Claims.Count()); } - - [TestPriority(10000)] - [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] - public void DropDatabaseDone() - { - DropDb(); - } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/SqlStoreTestBase.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/SqlStoreTestBase.cs index 7adfeb7cf8..5c3ae5a7b5 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/SqlStoreTestBase.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/SqlStoreTestBase.cs @@ -11,18 +11,22 @@ using Microsoft.AspNet.Identity.Test; using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing.xunit; using Microsoft.Data.Entity; -using Microsoft.Data.Entity.Storage; using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { - public abstract class SqlStoreTestBase : UserManagerTestBase + public abstract class SqlStoreTestBase : UserManagerTestBase, IClassFixture where TUser : IdentityUser, new() where TRole : IdentityRole, new() where TKey : IEquatable { - public abstract string ConnectionString { get; } + private readonly ScratchDatabaseFixture _fixture; + + protected SqlStoreTestBase(ScratchDatabaseFixture fixture) + { + _fixture = fixture; + } protected override bool ShouldSkipDbTests() { @@ -58,40 +62,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test protected override Expression> UserNameStartsWithPredicate(string userName) => u => u.UserName.StartsWith(userName); - - [TestPriority(-1000)] - [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] - public void DropDatabaseStart() + public TestDbContext CreateContext() { - DropDb(); - } - - [TestPriority(10000)] - [ConditionalFact] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] - public void DropDatabaseDone() - { - DropDb(); - } - - public void DropDb() - { - var db = DbUtil.Create(ConnectionString); - db.Database.EnsureDeleted(); - } - - public TestDbContext CreateContext(bool delete = false) - { - var db = DbUtil.Create(ConnectionString); - if (delete) - { - db.Database.EnsureDeleted(); - } + var db = DbUtil.Create(_fixture.ConnectionString); db.Database.EnsureCreated(); return db; } @@ -116,11 +89,6 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test user.PasswordHash = hashedPassword; } - public void EnsureDatabase() - { - CreateContext(); - } - [ConditionalFact] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] [OSSkipCondition(OperatingSystems.Linux)] diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreGuidKeyTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreGuidKeyTest.cs index 3945d6405f..7eaa4aba8a 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreGuidKeyTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreGuidKeyTest.cs @@ -25,17 +25,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] public class UserStoreGuidTest : SqlStoreTestBase { - private readonly string _connectionString = @"Server=(localdb)\mssqllocaldb;Database=SqlUserStoreGuidTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;Connection Timeout=30"; - - public override string ConnectionString + public UserStoreGuidTest(ScratchDatabaseFixture fixture) + : base(fixture) { - get - { - return _connectionString; - } } public class ApplicationUserStore : UserStore diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreIntKeyTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreIntKeyTest.cs index 788602e4a4..9db6702274 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreIntKeyTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreIntKeyTest.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { @@ -22,17 +21,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] public class UserStoreIntTest : SqlStoreTestBase { - private readonly string _connectionString = @"Server=(localdb)\mssqllocaldb;Database=SqlUserStoreIntTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;Connection Timeout=30"; - - public override string ConnectionString + public UserStoreIntTest(ScratchDatabaseFixture fixture) + : base(fixture) { - get - { - return _connectionString; - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreStringKeyTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreStringKeyTest.cs index 6c1faad18a..b66c9ee2fe 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreStringKeyTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreStringKeyTest.cs @@ -2,11 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] public class StringUser : IdentityUser { public StringUser() @@ -25,17 +23,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] public class UserStoreStringKeyTest : SqlStoreTestBase { - private readonly string _connectionString = @"Server=(localdb)\mssqllocaldb;Database=SqlUserStoreStringTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;Connection Timeout=30"; - - public override string ConnectionString + public UserStoreStringKeyTest(ScratchDatabaseFixture fixture) + : base(fixture) { - get - { - return _connectionString; - } } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs index 12c95734f7..c74ff816a4 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs @@ -6,60 +6,33 @@ using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using Microsoft.AspNet.Identity.Test; -using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing.xunit; +using Microsoft.AspNet.Testing; using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Microsoft.AspNet.Identity.EntityFramework.Test { - [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] - public class UserStoreTest : UserManagerTestBase + public class UserStoreTest : UserManagerTestBase, IClassFixture { - public class ApplicationDbContext : IdentityDbContext { } + private readonly ScratchDatabaseFixture _fixture; - private readonly string ConnectionString = @"Server=(localdb)\mssqllocaldb;Database=SqlUserStoreTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;Connection Timeout=30"; + public UserStoreTest(ScratchDatabaseFixture fixture) + { + _fixture = fixture; + } protected override bool ShouldSkipDbTests() - { - return TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows; - } + => TestPlatformHelper.IsMono || !TestPlatformHelper.IsWindows; - [TestPriority(-1000)] - [Fact] - public void DropDatabaseStart() - { - if (ShouldSkipDbTests()) - { - return; - } - DropDb(); - } + public class ApplicationDbContext : IdentityDbContext { } - [TestPriority(10000)] - [Fact] - public void DropDatabaseDone() - { - if (ShouldSkipDbTests()) - { - return; - } - DropDb(); - } - - public void DropDb() - { - var db = DbUtil.Create(ConnectionString); - db.Database.EnsureDeleted(); - } - - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public void CanCreateUserUsingEF() { - if (ShouldSkipDbTests()) - { - return; - } using (var db = CreateContext()) { var guid = Guid.NewGuid().ToString(); @@ -72,7 +45,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public IdentityDbContext CreateContext(bool delete = false) { - var db = DbUtil.Create(ConnectionString); + var db = DbUtil.Create(_fixture.ConnectionString); if (delete) { db.Database.EnsureDeleted(); @@ -93,7 +66,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test public ApplicationDbContext CreateAppContext() { - var db = DbUtil.Create(ConnectionString); + var db = DbUtil.Create(_fixture.ConnectionString); db.Database.EnsureCreated(); return db; } @@ -207,13 +180,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test await Assert.ThrowsAsync("roleName", async () => await store.IsInRoleAsync(new IdentityUser("fake"), "")); } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task CanCreateUsingManager() { - if (ShouldSkipDbTests()) - { - return; - } var manager = CreateManager(); var guid = Guid.NewGuid().ToString(); var user = new IdentityUser { UserName = "New" + guid }; @@ -221,13 +193,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user)); } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task TwoUsersSamePasswordDifferentHash() { - if (ShouldSkipDbTests()) - { - return; - } var manager = CreateManager(); var userA = new IdentityUser(Guid.NewGuid().ToString()); IdentityResultAssert.IsSuccess(await manager.CreateAsync(userA, "password")); @@ -237,13 +208,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test Assert.NotEqual(userA.PasswordHash, userB.PasswordHash); } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task AddUserToUnknownRoleFails() { - if (ShouldSkipDbTests()) - { - return; - } var manager = CreateManager(); var u = CreateTestUser(); IdentityResultAssert.IsSuccess(await manager.CreateAsync(u)); @@ -251,13 +221,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test async () => await manager.AddToRoleAsync(u, "bogus")); } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentUpdatesWillFail() { - if (ShouldSkipDbTests()) - { - return; - } var user = CreateTestUser(); using (var db = CreateContext()) { @@ -281,13 +250,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentUpdatesWillFailWithDetachedUser() { - if (ShouldSkipDbTests()) - { - return; - } var user = CreateTestUser(); using (var db = CreateContext()) { @@ -309,13 +277,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteAModifiedUserWillFail() { - if (ShouldSkipDbTests()) - { - return; - } var user = CreateTestUser(); using (var db = CreateContext()) { @@ -338,13 +305,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentRoleUpdatesWillFail() { - if (ShouldSkipDbTests()) - { - return; - } var role = new IdentityRole(Guid.NewGuid().ToString()); using (var db = CreateContext()) { @@ -368,13 +334,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task ConcurrentRoleUpdatesWillFailWithDetachedRole() { - if (ShouldSkipDbTests()) - { - return; - } var role = new IdentityRole(Guid.NewGuid().ToString()); using (var db = CreateContext()) { @@ -397,13 +362,12 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test } } - [Fact] + [ConditionalFact] + [FrameworkSkipCondition(RuntimeFrameworks.Mono)] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] public async Task DeleteAModifiedRoleWillFail() { - if (ShouldSkipDbTests()) - { - return; - } var role = new IdentityRole(Guid.NewGuid().ToString()); using (var db = CreateContext()) { diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/EntityFrameworkServiceBuilderExtension.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/EntityFrameworkServiceBuilderExtension.cs new file mode 100644 index 0000000000..edc3fc6e9d --- /dev/null +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/EntityFrameworkServiceBuilderExtension.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Data.Entity.Infrastructure; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class EntityFrameworkServiceBuilderExtension + { + public static IServiceCollection ServiceCollection(this EntityFrameworkServicesBuilder services) + => services.GetInfrastructure(); + } +} diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/ScratchDatabaseFixture.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/ScratchDatabaseFixture.cs new file mode 100644 index 0000000000..6872a528ae --- /dev/null +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/ScratchDatabaseFixture.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.Identity.EntityFramework.Test.Utilities; +using Microsoft.Data.Entity.Internal; + +namespace Microsoft.AspNet.Identity.EntityFramework.Test +{ + public class ScratchDatabaseFixture : IDisposable + { + private LazyRef _testStore; + + public ScratchDatabaseFixture() + { + _testStore = new LazyRef(() => SqlServerTestStore.CreateScratch()); + } + + public string ConnectionString => _testStore.Value.Connection.ConnectionString; + + public void Dispose() + { + if (_testStore.HasValue) + { + _testStore.Value?.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/SqlServerTestStore.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/SqlServerTestStore.cs new file mode 100644 index 0000000000..e3ea835cc1 --- /dev/null +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/SqlServerTestStore.cs @@ -0,0 +1,165 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Data.Common; +using System.Data.SqlClient; +using System.IO; +using System.Threading; + +namespace Microsoft.AspNet.Identity.EntityFramework.Test.Utilities +{ + public class SqlServerTestStore : IDisposable + { + public const int CommandTimeout = 90; + + public static string CreateConnectionString(string name) + { + var connStrBuilder = new SqlConnectionStringBuilder(TestEnvironment.Config["Test:SqlServer:DefaultConnectionString"]) + { + InitialCatalog = name + }; + + return connStrBuilder.ConnectionString; + } + + public static SqlServerTestStore CreateScratch(bool createDatabase = true) + => new SqlServerTestStore(GetScratchDbName()).CreateTransient(createDatabase); + + private SqlConnection _connection; + private readonly string _name; + private bool _deleteDatabase; + + private SqlServerTestStore(string name) + { + _name = name; + } + + private static string GetScratchDbName() + { + string name; + do + { + name = "Scratch_" + Guid.NewGuid(); + } while (DatabaseExists(name) + || DatabaseFilesExist(name)); + + return name; + } + + private static void WaitForExists(SqlConnection connection) + { + var retryCount = 0; + while (true) + { + try + { + connection.Open(); + + connection.Close(); + + return; + } + catch (SqlException e) + { + if (++retryCount >= 30 + || (e.Number != 233 && e.Number != -2 && e.Number != 4060)) + { + throw; + } + + SqlConnection.ClearPool(connection); + + Thread.Sleep(100); + } + } + } + + private SqlServerTestStore CreateTransient(bool createDatabase) + { + _connection = new SqlConnection(CreateConnectionString(_name)); + + if (createDatabase) + { + using (var master = new SqlConnection(CreateConnectionString("master"))) + { + master.Open(); + using (var command = master.CreateCommand()) + { + command.CommandTimeout = CommandTimeout; + command.CommandText = $"{Environment.NewLine}CREATE DATABASE [{_name}]"; + + command.ExecuteNonQuery(); + + WaitForExists(_connection); + } + } + _connection.Open(); + } + + _deleteDatabase = true; + return this; + } + + private static bool DatabaseExists(string name) + { + using (var master = new SqlConnection(CreateConnectionString("master"))) + { + master.Open(); + + using (var command = master.CreateCommand()) + { + command.CommandTimeout = CommandTimeout; + command.CommandText = $@"SELECT COUNT(*) FROM sys.databases WHERE name = N'{name}'"; + + return (int) command.ExecuteScalar() > 0; + } + } + } + + private static bool DatabaseFilesExist(string name) + { + var userFolder = Environment.GetEnvironmentVariable("USERPROFILE") ?? + Environment.GetEnvironmentVariable("HOME"); + return userFolder != null + && (File.Exists(Path.Combine(userFolder, name + ".mdf")) + || File.Exists(Path.Combine(userFolder, name + "_log.ldf"))); + } + + private void DeleteDatabase(string name) + { + using (var master = new SqlConnection(CreateConnectionString("master"))) + { + master.Open(); + + using (var command = master.CreateCommand()) + { + command.CommandTimeout = CommandTimeout; + // Query will take a few seconds if (and only if) there are active connections + + // SET SINGLE_USER will close any open connections that would prevent the drop + command.CommandText + = string.Format(@"IF EXISTS (SELECT * FROM sys.databases WHERE name = N'{0}') + BEGIN + ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; + DROP DATABASE [{0}]; + END", name); + + command.ExecuteNonQuery(); + } + } + } + + public DbConnection Connection => _connection; + + public void Dispose() + { + _connection.Dispose(); + + if (_deleteDatabase) + { + DeleteDatabase(_name); + } + } + } +} diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/TestEnvironment.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/TestEnvironment.cs new file mode 100644 index 0000000000..cd749944c9 --- /dev/null +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/Utilities/TestEnvironment.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Configuration; + +namespace Microsoft.AspNet.Identity.EntityFramework.Test.Utilities +{ + public static class TestEnvironment + { + public static IConfiguration Config { get; } + + static TestEnvironment() + { + var configBuilder = new ConfigurationBuilder() + .SetBasePath(".") + .AddJsonFile("config.json", optional: true) + .AddJsonFile("config.test.json", optional: true) + .AddEnvironmentVariables(); + + Config = configBuilder.Build(); + } + } +} diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/config.json b/test/Microsoft.AspNet.Identity.EntityFramework.Test/config.json new file mode 100644 index 0000000000..a39052b5ed --- /dev/null +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/config.json @@ -0,0 +1,7 @@ +{ + "Test": { + "SqlServer": { + "DefaultConnectionString": "Server=(localdb)\\MSSqlLocaldb;Integrated Security=true;MultipleActiveResultSets=true;Connect Timeout=30" + } + } +}