Move Database Error Page tests to SQLite

In an attempt to make them more reliable.

See also https://github.com/aspnet/EntityFrameworkCore/issues/15997
This commit is contained in:
Arthur Vickers 2019-06-07 14:58:31 -07:00
parent d3d6e0e709
commit b5adc6b156
10 changed files with 56 additions and 96 deletions

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
@ -131,6 +132,12 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
{
var databaseExists = await relationalDatabaseCreator.ExistsAsync();
if (databaseExists)
{
// Also check if the database is completely empty - see https://github.com/aspnet/EntityFrameworkCore/issues/15997
databaseExists = (bool)typeof(RelationalDatabaseCreator).GetMethod("HasTables", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(relationalDatabaseCreator, null);
}
var migrationsAssembly = context.GetService<IMigrationsAssembly>();
var modelDiffer = context.GetService<IMigrationsModelDiffer>();

View File

@ -80,13 +80,13 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Existing_database_not_using_migrations_exception_passes_thru()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
TestServer server = SetupTestServer<BloggingContext, DatabaseErrorButNoMigrationsMiddleware>(database);
var ex = await Assert.ThrowsAsync<DbUpdateException>(async () =>
await server.CreateClient().GetAsync("http://localhost/"));
Assert.Equal("Invalid column name 'Name'.", ex.InnerException.Message);
Assert.Equal("SQLite Error 1: 'no such table: Blogs'.", ex.InnerException.Message);
}
}
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{
var db = context.RequestServices.GetService<BloggingContext>();
db.Database.EnsureCreated();
db.Database.ExecuteSqlRaw("ALTER TABLE dbo.Blogs DROP COLUMN Name");
db.Database.ExecuteSqlRaw("ALTER TABLE Blogs RENAME TO Bloogs");
db.Blogs.Add(new Blog());
db.SaveChanges();
@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Error_page_displayed_no_migrations()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
TestServer server = SetupTestServer<BloggingContext, NoMigrationsMiddleware>(database);
HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public void No_exception_on_diagnostic_event_received_when_null_state()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
using (var server = SetupTestServer<BloggingContext, NoMigrationsMiddleware>(database))
{
@ -158,7 +158,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
}
catch (Exception e)
{
Assert.Equal("SqlException", e.GetType().Name);
Assert.Equal("DbUpdateException", e.GetType().Name);
}
}
}
@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Error_page_displayed_pending_migrations()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
TestServer server = SetupTestServer<BloggingContextWithMigrations, PendingMigrationsMiddleware>(database);
HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
@ -206,7 +206,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Error_page_displayed_pending_model_changes()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
TestServer server = SetupTestServer<BloggingContextWithPendingModelChanges, PendingModelChangesMiddleware>(database);
HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Error_page_then_apply_migrations()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
TestServer server = SetupTestServer<BloggingContextWithMigrations, ApplyMigrationsMiddleware>(database);
var client = server.CreateClient();
@ -300,7 +300,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{
var migrationsEndpoint = "/MyCustomEndPoints/ApplyMyMigrationsHere";
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
var builder = new WebHostBuilder()
.Configure(app =>
@ -314,10 +314,8 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
})
.ConfigureServices(services =>
{
services.AddDbContext<BloggingContextWithMigrations>(optionsBuilder =>
{
optionsBuilder.UseSqlServer(database.ConnectionString);
});
services.AddDbContext<BloggingContextWithMigrations>(
optionsBuilder => optionsBuilder.UseSqlite(database.ConnectionString));
});
var server = new TestServer(builder);
@ -355,8 +353,8 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
catch (Exception exception)
{
Assert.True(
exception.GetType().Name == "SqlException"
|| exception.InnerException?.GetType().Name == "SqlException");
exception.GetType().Name == "SqliteException"
|| exception.InnerException?.GetType().Name == "SqliteException");
}
Assert.Contains(logProvider.Logger.Messages.ToList(), m =>
@ -370,18 +368,11 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
public virtual Task Invoke(HttpContext context)
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
var optionsBuilder = new DbContextOptionsBuilder()
.UseLoggerFactory(context.RequestServices.GetService<ILoggerFactory>());
if (!PlatformHelper.IsMono)
{
optionsBuilder.UseSqlServer(database.ConnectionString, b => b.CommandTimeout(600).EnableRetryOnFailure());
}
else
{
optionsBuilder.UseInMemoryDatabase("Scratch");
}
.UseLoggerFactory(context.RequestServices.GetService<ILoggerFactory>())
.UseSqlite(database.ConnectionString);
var db = new BloggingContext(optionsBuilder.Options);
db.Blogs.Add(new Blog());
@ -396,7 +387,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Pass_thru_when_exception_in_logic()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
var logProvider = new TestLoggerProvider();
@ -409,8 +400,8 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
catch (Exception exception)
{
Assert.True(
exception.GetType().Name == "SqlException"
|| exception.InnerException?.GetType().Name == "SqlException");
exception.GetType().Name == "SqliteException"
|| exception.InnerException?.GetType().Name == "SqliteException");
}
Assert.Contains(logProvider.Logger.Messages.ToList(), m =>
@ -437,7 +428,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Error_page_displayed_when_exception_wrapped()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
TestServer server = SetupTestServer<BloggingContext, WrappedExceptionMiddleware>(database);
HttpResponseMessage response = await server.CreateClient().GetAsync("http://localhost/");
@ -470,7 +461,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
}
}
private static TestServer SetupTestServer<TContext, TMiddleware>(SqlServerTestStore database, ILoggerProvider logProvider = null)
private static TestServer SetupTestServer<TContext, TMiddleware>(SqlTestStore database, ILoggerProvider logProvider = null)
where TContext : DbContext
{
var builder = new WebHostBuilder()
@ -489,20 +480,9 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
})
.ConfigureServices(services =>
{
services.AddDbContext<TContext>(optionsBuilder =>
{
if (!PlatformHelper.IsMono)
{
optionsBuilder.UseSqlServer(
database.ConnectionString,
b => b.CommandTimeout(600).EnableRetryOnFailure());
}
else
{
optionsBuilder.UseInMemoryDatabase("Scratch");
}
});
services.AddDbContext<TContext>(optionsBuilder => optionsBuilder.UseSqlite(database.ConnectionString));
});
return new TestServer(builder);
}

View File

@ -4,14 +4,12 @@
<TargetFramework>netcoreapp3.0</TargetFramework>
<!-- Mitigation for long path issues -->
<AssemblyName>Diagnostics.EFCore.FunctionalTests</AssemblyName>
<TestDependsOnMssql>true</TestDependsOnMssql>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
<Reference Include="Microsoft.AspNetCore.TestHost" />
<Reference Include="Microsoft.EntityFrameworkCore.InMemory" />
<Reference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<Reference Include="Microsoft.EntityFrameworkCore.Sqlite" />
</ItemGroup>
</Project>

View File

@ -68,10 +68,10 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
private async Task Migration_request(bool useCustomPath)
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(database.ConnectionString);
optionsBuilder.UseSqlite(database.ConnectionString);
var path = useCustomPath ? new PathString("/EndPoints/ApplyMyMigrations") : MigrationsEndPointOptions.DefaultPath;
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{
services.AddDbContext<BloggingContextWithMigrations>(options =>
{
options.UseSqlServer(database.ConnectionString);
options.UseSqlite(database.ConnectionString);
});
});
var server = new TestServer(builder);
@ -174,7 +174,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{
var builder = new WebHostBuilder()
.Configure(app => app.UseMigrationsEndPoint())
.ConfigureServices(services => services.AddEntityFrameworkSqlServer());
.ConfigureServices(services => services.AddEntityFrameworkSqlite());
var server = new TestServer(builder);
var formData = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
@ -195,7 +195,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
[OSSkipCondition(OperatingSystems.MacOSX)]
public async Task Exception_while_applying_migrations()
{
using (var database = SqlServerTestStore.CreateScratch())
using (var database = SqlTestStore.CreateScratch())
{
var builder = new WebHostBuilder()
.Configure(app => app.UseMigrationsEndPoint())
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{
services.AddDbContext<BloggingContextWithSnapshotThatThrows>(optionsBuilder =>
{
optionsBuilder.UseSqlServer(database.ConnectionString);
optionsBuilder.UseSqlite(database.ConnectionString);
});
});
var server = new TestServer(builder);
@ -221,4 +221,4 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
}
}
}
}
}

View File

@ -2,52 +2,29 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Helpers;
using Microsoft.EntityFrameworkCore;
namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{
public class SqlServerTestStore : IDisposable
public class SqlTestStore : IDisposable
{
private static int _scratchCount;
public static SqlTestStore CreateScratch() => new SqlTestStore($"D{Guid.NewGuid()}");
public static SqlServerTestStore CreateScratch()
private SqlTestStore(string name)
{
var name = "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.FunctionalTests.Scratch_" + Interlocked.Increment(ref _scratchCount);
var db = new SqlServerTestStore(name);
return db;
ConnectionString = $"Data Source = {name}.db";
}
private readonly string _connectionString;
private SqlServerTestStore(string name)
{
_connectionString = $@"Server=(localdb)\mssqllocaldb;Database={name};Timeout=600";
}
public string ConnectionString
{
get { return _connectionString; }
}
public string ConnectionString { get; }
private void EnsureDeleted()
{
if (!PlatformHelper.IsMono)
using (var db = new DbContext(new DbContextOptionsBuilder().UseSqlite(ConnectionString).Options))
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(_connectionString, b => b.CommandTimeout(600).EnableRetryOnFailure());
using (var db = new DbContext(optionsBuilder.Options))
{
db.Database.EnsureDeleted();
}
db.Database.EnsureDeleted();
}
}
public virtual void Dispose()
{
EnsureDeleted();
}
public virtual void Dispose() => EnsureDeleted();
}
}

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
migrationBuilder.CreateTable("Blogs",
c => new
{
BlogId = c.Column<int>().Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
BlogId = c.Column<int>().Annotation("Sqlite:Autoincrement", true),
Name = c.Column<string>(nullable: true),
})
.PrimaryKey("PK_Blog", t => t.BlogId);
@ -68,4 +68,4 @@ namespace Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.Tests
{ }
}
}
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
@ -12,7 +12,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
<Reference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<Reference Include="Microsoft.EntityFrameworkCore.Sqlite" />
</ItemGroup>
</Project>

View File

@ -12,7 +12,7 @@ namespace DatabaseErrorPageSample
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyContext>(
options => options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=DatabaseErrorPageSample;Trusted_Connection=True;"));
options => options.UseSqlite($"Data Source = DatabaseErrorPageSample.db"));
}
public void Configure(IApplicationBuilder app)

View File

@ -32,10 +32,8 @@ namespace HealthChecksSample
//
// The health check added by AddDbContextCheck will create instances of MyContext from the service provider,
// and so will reuse the configuration provided here.
services.AddDbContext<MyContext>(options =>
{
options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);
});
services.AddDbContext<MyContext>(
options => options.UseSqlite(Configuration["ConnectionStrings:DefaultConnection"]));
}
public void Configure(IApplicationBuilder app)

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
@ -8,7 +8,7 @@
<Reference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" />
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
<Reference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<Reference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<Reference Include="Microsoft.Extensions.Configuration.CommandLine" />
<Reference Include="Microsoft.Extensions.Configuration.Json" />
<Reference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" />