Identity/MusicStore/ErrorPage test re-anabling
Fixes #10672 #7925 #10670 Also, moves MusicStore tests to SQLite for better reliability
This commit is contained in:
parent
400835e0b4
commit
173cf1786e
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Data.SqlClient;
|
|
||||||
using Microsoft.AspNetCore.Builder.Internal;
|
using Microsoft.AspNetCore.Builder.Internal;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
|
|
@ -24,59 +23,73 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||||
|
|
||||||
services
|
services
|
||||||
.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build())
|
.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build())
|
||||||
.AddDbContext<IdentityDbContext>(o =>
|
.AddDbContext<VerstappenDbContext>(o =>
|
||||||
o.UseSqlite(fixture.Connection)
|
o.UseSqlite(fixture.Connection)
|
||||||
.ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning)))
|
.ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning)))
|
||||||
.AddIdentity<IdentityUser, IdentityRole>(o => o.Stores.MaxLengthForKeys = 128)
|
.AddIdentity<IdentityUser, IdentityRole>(o => o.Stores.MaxLengthForKeys = 128)
|
||||||
.AddEntityFrameworkStores<IdentityDbContext>();
|
.AddEntityFrameworkStores<VerstappenDbContext>();
|
||||||
|
|
||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
|
|
||||||
var provider = services.BuildServiceProvider();
|
_builder = new ApplicationBuilder(services.BuildServiceProvider());
|
||||||
_builder = new ApplicationBuilder(provider);
|
|
||||||
|
|
||||||
using (var scoped = provider.GetRequiredService<IServiceScopeFactory>().CreateScope())
|
using (var scope = _builder.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
|
||||||
using (var db = scoped.ServiceProvider.GetRequiredService<IdentityDbContext>())
|
|
||||||
{
|
{
|
||||||
db.Database.EnsureCreated();
|
scope.ServiceProvider.GetRequiredService<VerstappenDbContext>().Database.EnsureCreated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalFact(Skip = "https://github.com/aspnet/AspNetCore/issues/7925")]
|
// Need a different context type here since EF model is changing by having MaxLengthForKeys
|
||||||
|
public class VerstappenDbContext : IdentityDbContext<IdentityUser, IdentityRole, string>
|
||||||
|
{
|
||||||
|
public VerstappenDbContext(DbContextOptions options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalFact]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[OSSkipCondition(OperatingSystems.Linux)]
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
public void EnsureDefaultSchema()
|
public void EnsureDefaultSchema()
|
||||||
{
|
{
|
||||||
var db = _builder.ApplicationServices.GetRequiredService<IdentityDbContext>();
|
using (var scope = _builder.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
|
||||||
VerifyDefaultSchema(db);
|
{
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<VerstappenDbContext>();
|
||||||
|
|
||||||
|
VerifyDefaultSchema(db);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void VerifyDefaultSchema(IdentityDbContext dbContext)
|
private static void VerifyDefaultSchema(VerstappenDbContext dbContext)
|
||||||
{
|
{
|
||||||
var sqlConn = dbContext.Database.GetDbConnection();
|
var sqlConn = (SqliteConnection)dbContext.Database.GetDbConnection();
|
||||||
|
|
||||||
using (var db = new SqliteConnection(sqlConn.ConnectionString))
|
try
|
||||||
{
|
{
|
||||||
db.Open();
|
sqlConn.Open();
|
||||||
Assert.True(DbUtil.VerifyColumns(db, "AspNetUsers", "Id", "UserName", "Email", "PasswordHash", "SecurityStamp",
|
Assert.True(DbUtil.VerifyColumns(sqlConn, "AspNetUsers", "Id", "UserName", "Email", "PasswordHash", "SecurityStamp",
|
||||||
"EmailConfirmed", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnabled",
|
"EmailConfirmed", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnabled",
|
||||||
"LockoutEnd", "AccessFailedCount", "ConcurrencyStamp", "NormalizedUserName", "NormalizedEmail"));
|
"LockoutEnd", "AccessFailedCount", "ConcurrencyStamp", "NormalizedUserName", "NormalizedEmail"));
|
||||||
Assert.True(DbUtil.VerifyColumns(db, "AspNetRoles", "Id", "Name", "NormalizedName", "ConcurrencyStamp"));
|
Assert.True(DbUtil.VerifyColumns(sqlConn, "AspNetRoles", "Id", "Name", "NormalizedName", "ConcurrencyStamp"));
|
||||||
Assert.True(DbUtil.VerifyColumns(db, "AspNetUserRoles", "UserId", "RoleId"));
|
Assert.True(DbUtil.VerifyColumns(sqlConn, "AspNetUserRoles", "UserId", "RoleId"));
|
||||||
Assert.True(DbUtil.VerifyColumns(db, "AspNetUserClaims", "Id", "UserId", "ClaimType", "ClaimValue"));
|
Assert.True(DbUtil.VerifyColumns(sqlConn, "AspNetUserClaims", "Id", "UserId", "ClaimType", "ClaimValue"));
|
||||||
Assert.True(DbUtil.VerifyColumns(db, "AspNetUserLogins", "UserId", "ProviderKey", "LoginProvider", "ProviderDisplayName"));
|
Assert.True(DbUtil.VerifyColumns(sqlConn, "AspNetUserLogins", "UserId", "ProviderKey", "LoginProvider", "ProviderDisplayName"));
|
||||||
Assert.True(DbUtil.VerifyColumns(db, "AspNetUserTokens", "UserId", "LoginProvider", "Name", "Value"));
|
Assert.True(DbUtil.VerifyColumns(sqlConn, "AspNetUserTokens", "UserId", "LoginProvider", "Name", "Value"));
|
||||||
|
|
||||||
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUsers", 256, "UserName", "Email", "NormalizedUserName", "NormalizedEmail"));
|
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUsers", 256, "UserName", "Email", "NormalizedUserName", "NormalizedEmail"));
|
||||||
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetRoles", 256, "Name", "NormalizedName"));
|
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetRoles", 256, "Name", "NormalizedName"));
|
||||||
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUserLogins", 128, "LoginProvider", "ProviderKey"));
|
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUserLogins", 128, "LoginProvider", "ProviderKey"));
|
||||||
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUserTokens", 128, "LoginProvider", "Name"));
|
Assert.True(DbUtil.VerifyMaxLength(dbContext, "AspNetUserTokens", 128, "LoginProvider", "Name"));
|
||||||
|
|
||||||
DbUtil.VerifyIndex(db, "AspNetRoles", "RoleNameIndex", isUnique: true);
|
DbUtil.VerifyIndex(sqlConn, "AspNetRoles", "RoleNameIndex", isUnique: true);
|
||||||
DbUtil.VerifyIndex(db, "AspNetUsers", "UserNameIndex", isUnique: true);
|
DbUtil.VerifyIndex(sqlConn, "AspNetUsers", "UserNameIndex", isUnique: true);
|
||||||
DbUtil.VerifyIndex(db, "AspNetUsers", "EmailIndex");
|
DbUtil.VerifyIndex(sqlConn, "AspNetUsers", "EmailIndex");
|
||||||
db.Close();
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
sqlConn.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Identity.Test;
|
using Microsoft.AspNetCore.Identity.Test;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -105,10 +106,10 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||||
public InkProtector() { }
|
public InkProtector() { }
|
||||||
|
|
||||||
public string Unprotect(string keyId, string data)
|
public string Unprotect(string keyId, string data)
|
||||||
=> "ink";
|
=> data?.Substring(4);
|
||||||
|
|
||||||
public string Protect(string keyId, string data)
|
public string Protect(string keyId, string data)
|
||||||
=> "ink";
|
=> "ink:" + data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CustomUser : IdentityUser
|
private class CustomUser : IdentityUser
|
||||||
|
|
@ -133,8 +134,8 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||||
{
|
{
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
{
|
{
|
||||||
Assert.Equal("Default:ink", reader.GetString(0));
|
var value = reader.GetString(0);
|
||||||
return reader.GetString(0) == "Default:ink";
|
return value.StartsWith("Default:ink:");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -155,8 +156,8 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||||
{
|
{
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
{
|
{
|
||||||
Assert.Equal("Default:ink", reader.GetString(0));
|
var value = reader.GetString(0);
|
||||||
return reader.GetString(0) == "Default:ink";
|
return value.StartsWith("Default:ink:");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,75 +168,103 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||||
/// Test.
|
/// Test.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task</returns>
|
/// <returns>Task</returns>
|
||||||
[Theory(Skip = "https://github.com/aspnet/AspNetCore/issues/7925")]
|
[Fact]
|
||||||
[InlineData(true)]
|
public Task CustomPersonalDataPropertiesCanBeProtected()
|
||||||
[InlineData(false)]
|
=> CustomPersonalDataPropertiesAreProtected<ProtectedIdentityDbContext>(true);
|
||||||
public async Task CustomPersonalDataPropertiesAreProtected(bool protect)
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Task</returns>
|
||||||
|
[Fact]
|
||||||
|
public Task CustomPersonalDataPropertiesCanBeNotProtected()
|
||||||
|
=> CustomPersonalDataPropertiesAreProtected<UnprotectedIdentityDbContext>(false);
|
||||||
|
|
||||||
|
private async Task CustomPersonalDataPropertiesAreProtected<TContext>(bool protect)
|
||||||
|
where TContext : DbContext
|
||||||
{
|
{
|
||||||
using (var scratch = new ScratchDatabaseFixture())
|
using (var connection = new SqliteConnection($"DataSource=D{Guid.NewGuid()}.db"))
|
||||||
{
|
{
|
||||||
var services = new ServiceCollection().AddLogging();
|
var services = new ServiceCollection().AddLogging();
|
||||||
services.AddIdentity<CustomUser, IdentityRole>(options =>
|
services.AddIdentity<CustomUser, IdentityRole>(options =>
|
||||||
{
|
{
|
||||||
options.Stores.ProtectPersonalData = protect;
|
options.Stores.ProtectPersonalData = protect;
|
||||||
})
|
})
|
||||||
.AddEntityFrameworkStores<IdentityDbContext<CustomUser>>()
|
.AddEntityFrameworkStores<TContext>()
|
||||||
.AddPersonalDataProtection<InkProtector, DefaultKeyRing>();
|
.AddPersonalDataProtection<InkProtector, DefaultKeyRing>();
|
||||||
|
|
||||||
var dbOptions = new DbContextOptionsBuilder().UseSqlite(scratch.Connection)
|
services.AddDbContext<TContext>(b => b.UseSqlite(connection));
|
||||||
.UseApplicationServiceProvider(services.BuildServiceProvider())
|
|
||||||
.Options;
|
|
||||||
var dbContext = new IdentityDbContext<CustomUser>(dbOptions);
|
|
||||||
services.AddSingleton(dbContext);
|
|
||||||
dbContext.Database.EnsureCreated();
|
|
||||||
|
|
||||||
var sp = services.BuildServiceProvider();
|
var applicationServiceProvider = services.BuildServiceProvider();
|
||||||
var manager = sp.GetService<UserManager<CustomUser>>();
|
|
||||||
|
|
||||||
var guid = Guid.NewGuid().ToString();
|
using (var scope = applicationServiceProvider.CreateScope())
|
||||||
var user = new CustomUser();
|
|
||||||
user.Id = guid;
|
|
||||||
user.UserName = guid;
|
|
||||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
|
||||||
user.Email = "test@test.com";
|
|
||||||
user.PersonalData1 = "p1";
|
|
||||||
user.PersonalData2 = "p2";
|
|
||||||
user.NonPersonalData1 = "np1";
|
|
||||||
user.NonPersonalData2 = "np2";
|
|
||||||
user.SafePersonalData = "safe";
|
|
||||||
user.PhoneNumber = "12345678";
|
|
||||||
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
|
|
||||||
|
|
||||||
IdentityResultAssert.IsSuccess(await manager.ResetAuthenticatorKeyAsync(user));
|
|
||||||
IdentityResultAssert.IsSuccess(await manager.SetAuthenticationTokenAsync(user, "loginProvider", "token", "value"));
|
|
||||||
|
|
||||||
var conn = dbContext.Database.GetDbConnection();
|
|
||||||
conn.Open();
|
|
||||||
if (protect)
|
|
||||||
{
|
{
|
||||||
Assert.True(FindInk(conn, "PhoneNumber", guid));
|
var dbContext = scope.ServiceProvider.GetRequiredService<TContext>();
|
||||||
Assert.True(FindInk(conn, "Email", guid));
|
dbContext.Database.EnsureCreated();
|
||||||
Assert.True(FindInk(conn, "UserName", guid));
|
|
||||||
Assert.True(FindInk(conn, "PersonalData1", guid));
|
|
||||||
Assert.True(FindInk(conn, "PersonalData2", guid));
|
|
||||||
Assert.True(FindAuthenticatorKeyInk(conn, guid));
|
|
||||||
Assert.True(FindTokenInk(conn, guid, "loginProvider", "token"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert.False(FindInk(conn, "PhoneNumber", guid));
|
|
||||||
Assert.False(FindInk(conn, "Email", guid));
|
|
||||||
Assert.False(FindInk(conn, "UserName", guid));
|
|
||||||
Assert.False(FindInk(conn, "PersonalData1", guid));
|
|
||||||
Assert.False(FindInk(conn, "PersonalData2", guid));
|
|
||||||
Assert.False(FindAuthenticatorKeyInk(conn, guid));
|
|
||||||
Assert.False(FindTokenInk(conn, guid, "loginProvider", "token"));
|
|
||||||
}
|
|
||||||
Assert.False(FindInk(conn, "NonPersonalData1", guid));
|
|
||||||
Assert.False(FindInk(conn, "NonPersonalData2", guid));
|
|
||||||
Assert.False(FindInk(conn, "SafePersonalData", guid));
|
|
||||||
|
|
||||||
conn.Close();
|
var manager = scope.ServiceProvider.GetService<UserManager<CustomUser>>();
|
||||||
|
|
||||||
|
var guid = Guid.NewGuid().ToString();
|
||||||
|
var user = new CustomUser();
|
||||||
|
user.Id = guid;
|
||||||
|
user.UserName = guid;
|
||||||
|
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||||
|
user.Email = "test@test.com";
|
||||||
|
user.PersonalData1 = "p1";
|
||||||
|
user.PersonalData2 = "p2";
|
||||||
|
user.NonPersonalData1 = "np1";
|
||||||
|
user.NonPersonalData2 = "np2";
|
||||||
|
user.SafePersonalData = "safe";
|
||||||
|
user.PhoneNumber = "12345678";
|
||||||
|
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
|
||||||
|
|
||||||
|
IdentityResultAssert.IsSuccess(await manager.ResetAuthenticatorKeyAsync(user));
|
||||||
|
IdentityResultAssert.IsSuccess(await manager.SetAuthenticationTokenAsync(user, "loginProvider", "token", "value"));
|
||||||
|
|
||||||
|
connection.Open();
|
||||||
|
if (protect)
|
||||||
|
{
|
||||||
|
Assert.True(FindInk(connection, "PhoneNumber", guid));
|
||||||
|
Assert.True(FindInk(connection, "Email", guid));
|
||||||
|
Assert.True(FindInk(connection, "UserName", guid));
|
||||||
|
Assert.True(FindInk(connection, "PersonalData1", guid));
|
||||||
|
Assert.True(FindInk(connection, "PersonalData2", guid));
|
||||||
|
Assert.True(FindAuthenticatorKeyInk(connection, guid));
|
||||||
|
Assert.True(FindTokenInk(connection, guid, "loginProvider", "token"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.False(FindInk(connection, "PhoneNumber", guid));
|
||||||
|
Assert.False(FindInk(connection, "Email", guid));
|
||||||
|
Assert.False(FindInk(connection, "UserName", guid));
|
||||||
|
Assert.False(FindInk(connection, "PersonalData1", guid));
|
||||||
|
Assert.False(FindInk(connection, "PersonalData2", guid));
|
||||||
|
Assert.False(FindAuthenticatorKeyInk(connection, guid));
|
||||||
|
Assert.False(FindTokenInk(connection, guid, "loginProvider", "token"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.False(FindInk(connection, "NonPersonalData1", guid));
|
||||||
|
Assert.False(FindInk(connection, "NonPersonalData2", guid));
|
||||||
|
Assert.False(FindInk(connection, "SafePersonalData", guid));
|
||||||
|
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProtectedIdentityDbContext : IdentityDbContext<CustomUser>
|
||||||
|
{
|
||||||
|
public ProtectedIdentityDbContext(DbContextOptions<ProtectedIdentityDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UnprotectedIdentityDbContext : IdentityDbContext<CustomUser>
|
||||||
|
{
|
||||||
|
public UnprotectedIdentityDbContext(DbContextOptions<UnprotectedIdentityDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore.Test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalFact(Skip = "TODO: Fix for new EF. Issue #10670")]
|
[ConditionalFact]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[OSSkipCondition(OperatingSystems.Linux)]
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Diagnostics.FunctionalTests
|
||||||
|
|
||||||
public HttpClient Client { get; }
|
public HttpClient Client { get; }
|
||||||
|
|
||||||
[ConditionalFact(Skip = "TODO: EF query interception for opening connection. Issue #10672")]
|
[ConditionalFact]
|
||||||
[OSSkipCondition(OperatingSystems.Linux)]
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
public async Task DatabaseErrorPage_ShowsError()
|
public async Task DatabaseErrorPage_ShowsError()
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
// Retrieve Genre genre and its Associated associated Albums albums from database
|
// Retrieve Genre genre and its Associated associated Albums albums from database
|
||||||
var genreModel = await DbContext.Genres
|
var genreModel = await DbContext.Genres
|
||||||
.Include(g => g.Albums)
|
|
||||||
.Where(g => g.Name == genre)
|
.Where(g => g.Name == genre)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
|
@ -45,6 +44,8 @@ namespace MusicStore.Controllers
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await DbContext.Entry(genreModel).Collection(g => g.Albums).LoadAsync();
|
||||||
|
|
||||||
return View(genreModel);
|
return View(genreModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,13 @@ using System.Globalization;
|
||||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||||
using MusicStore.Components;
|
using MusicStore.Components;
|
||||||
using MusicStore.Mocks.Common;
|
using MusicStore.Mocks.Common;
|
||||||
|
|
@ -47,16 +44,9 @@ namespace MusicStore
|
||||||
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
||||||
|
|
||||||
// Add EF services to the services container
|
// Add EF services to the services container
|
||||||
if (_platform.UseInMemoryStore)
|
// Add EF services to the services container
|
||||||
{
|
services.AddDbContext<MusicStoreContext>(options =>
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
options.UseSqlite("Data Source=MusicStore.db"));
|
||||||
options.UseInMemoryDatabase("Scratch"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Identity services to the services container
|
// Add Identity services to the services container
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||||
using Microsoft.AspNetCore.Authentication.Twitter;
|
using Microsoft.AspNetCore.Authentication.Twitter;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MusicStore.Components;
|
using MusicStore.Components;
|
||||||
using MusicStore.Mocks.Common;
|
using MusicStore.Mocks.Common;
|
||||||
using MusicStore.Mocks.Facebook;
|
using MusicStore.Mocks.Facebook;
|
||||||
|
|
@ -50,16 +45,8 @@ namespace MusicStore
|
||||||
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
||||||
|
|
||||||
// Add EF services to the services container
|
// Add EF services to the services container
|
||||||
if (_platform.UseInMemoryStore)
|
services.AddDbContext<MusicStoreContext>(options =>
|
||||||
{
|
options.UseSqlite("Data Source=MusicStore.db"));
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseInMemoryDatabase("Scratch"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Identity services to the services container
|
// Add Identity services to the services container
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
|
|
|
||||||
|
|
@ -115,17 +115,18 @@ namespace MusicStore.Models
|
||||||
.SumAsync();
|
.SumAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<decimal> GetTotal()
|
public async Task<decimal> GetTotal()
|
||||||
{
|
{
|
||||||
// Multiply album price by count of that album to get
|
// Multiply album price by count of that album to get
|
||||||
// the current price for each of those albums in the cart
|
// the current price for each of those albums in the cart
|
||||||
// sum all album price totals to get the cart total
|
// sum all album price totals to get the cart total
|
||||||
|
|
||||||
return _dbContext
|
return (await _dbContext
|
||||||
.CartItems
|
.CartItems
|
||||||
.Where(c => c.CartId == _shoppingCartId)
|
.Where(c => c.CartId == _shoppingCartId)
|
||||||
.Select(c => c.Album.Price * c.Count)
|
.Select(c => c.Album.Price * c.Count)
|
||||||
.SumAsync();
|
.ToListAsync())
|
||||||
|
.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CreateOrder(Order order)
|
public async Task CreateOrder(Order order)
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@
|
||||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||||
<Reference Include="Microsoft.AspNetCore.Session" />
|
<Reference Include="Microsoft.AspNetCore.Session" />
|
||||||
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
|
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
|
||||||
<Reference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
<Reference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||||
<Reference Include="Microsoft.EntityFrameworkCore.SqlServer" />
|
|
||||||
<Reference Include="Microsoft.Extensions.Configuration.CommandLine" />
|
<Reference Include="Microsoft.Extensions.Configuration.CommandLine" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,10 @@ using System.Runtime.InteropServices;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MusicStore.Components;
|
using MusicStore.Components;
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
|
|
||||||
|
|
@ -40,16 +38,8 @@ namespace MusicStore
|
||||||
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
||||||
|
|
||||||
// Add EF services to the services container
|
// Add EF services to the services container
|
||||||
if (_platform.UseInMemoryStore)
|
services.AddDbContext<MusicStoreContext>(options =>
|
||||||
{
|
options.UseSqlite("Data Source=MusicStore.db"));
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseInMemoryDatabase("Scratch"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseSqlServer(Configuration[StoreConfig.ConnectionStringKey.Replace("__", ":")]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Identity services to the services container
|
// Add Identity services to the services container
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ namespace MusicStore
|
||||||
|
|
||||||
// Add EF services to the services container
|
// Add EF services to the services container
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
services.AddDbContext<MusicStoreContext>(options =>
|
||||||
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
|
options.UseSqlite("Data Source=MusicStore.db"));
|
||||||
|
|
||||||
// Add Identity services to the services container
|
// Add Identity services to the services container
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,10 @@ using System.Globalization;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||||
using MusicStore.Components;
|
using MusicStore.Components;
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
|
|
@ -57,16 +55,8 @@ namespace MusicStore
|
||||||
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
||||||
|
|
||||||
// Add EF services to the services container
|
// Add EF services to the services container
|
||||||
if (_platform.UseInMemoryStore)
|
services.AddDbContext<MusicStoreContext>(options =>
|
||||||
{
|
options.UseSqlite("Data Source=MusicStore.db"));
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseInMemoryDatabase("Scratch"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.AddDbContext<MusicStoreContext>(options =>
|
|
||||||
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Identity services to the services container
|
// Add Identity services to the services container
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,22 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.AspNetCore.Mvc.ViewComponents;
|
using Microsoft.AspNetCore.Mvc.ViewComponents;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using MusicStore.Controllers;
|
using MusicStore.Controllers;
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Components
|
namespace MusicStore.Components
|
||||||
{
|
{
|
||||||
public class CartSummaryComponentTest
|
public class CartSummaryComponentTest : IClassFixture<SqliteInMemoryFixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly SqliteInMemoryFixture _fixture;
|
||||||
|
|
||||||
public CartSummaryComponentTest()
|
public CartSummaryComponentTest(SqliteInMemoryFixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -45,7 +34,7 @@ namespace MusicStore.Components
|
||||||
viewContext.HttpContext.Session.SetString("Session", cartId);
|
viewContext.HttpContext.Session.SetString("Session", cartId);
|
||||||
|
|
||||||
// DbContext initialization
|
// DbContext initialization
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
PopulateData(dbContext, cartId, albumTitle: "AlbumA", itemCount: 10);
|
PopulateData(dbContext, cartId, albumTitle: "AlbumA", itemCount: 10);
|
||||||
|
|
||||||
// CartSummaryComponent initialization
|
// CartSummaryComponent initialization
|
||||||
|
|
@ -68,10 +57,20 @@ namespace MusicStore.Components
|
||||||
|
|
||||||
private static void PopulateData(MusicStoreContext context, string cartId, string albumTitle, int itemCount)
|
private static void PopulateData(MusicStoreContext context, string cartId, string albumTitle, int itemCount)
|
||||||
{
|
{
|
||||||
var album = new Album()
|
var album = new Album
|
||||||
{
|
{
|
||||||
AlbumId = 1,
|
AlbumId = 1,
|
||||||
Title = albumTitle,
|
Title = albumTitle,
|
||||||
|
Artist = new Artist
|
||||||
|
{
|
||||||
|
ArtistId = 1,
|
||||||
|
Name = "Kung Fu Kenny"
|
||||||
|
},
|
||||||
|
Genre = new Genre
|
||||||
|
{
|
||||||
|
GenreId = 1,
|
||||||
|
Name = "Rap"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var cartItems = Enumerable.Range(1, itemCount).Select(n =>
|
var cartItems = Enumerable.Range(1, itemCount).Select(n =>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
@ -15,29 +14,21 @@ using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Controllers
|
namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class CheckoutControllerTest
|
public class CheckoutControllerTest : IClassFixture<SqliteInMemoryFixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly SqliteInMemoryFixture _fixture;
|
||||||
|
|
||||||
public CheckoutControllerTest()
|
public CheckoutControllerTest(SqliteInMemoryFixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddressAndPayment_ReturnsDefaultView()
|
public void AddressAndPayment_ReturnsDefaultView()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = controller.AddressAndPayment();
|
var result = controller.AddressAndPayment();
|
||||||
|
|
@ -54,10 +45,7 @@ namespace MusicStore.Controllers
|
||||||
var httpContext = new DefaultHttpContext();
|
var httpContext = new DefaultHttpContext();
|
||||||
|
|
||||||
var orderId = 10;
|
var orderId = 10;
|
||||||
var order = new Order()
|
var order = CreateOrder(10);
|
||||||
{
|
|
||||||
OrderId = orderId,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Session initialization
|
// Session initialization
|
||||||
var cartId = "CartId_A";
|
var cartId = "CartId_A";
|
||||||
|
|
@ -76,7 +64,7 @@ namespace MusicStore.Controllers
|
||||||
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims));
|
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims));
|
||||||
|
|
||||||
// DbContext initialization
|
// DbContext initialization
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var cartItems = CreateTestCartItems(
|
var cartItems = CreateTestCartItems(
|
||||||
cartId,
|
cartId,
|
||||||
itemPrice: 10,
|
itemPrice: 10,
|
||||||
|
|
@ -85,7 +73,7 @@ namespace MusicStore.Controllers
|
||||||
dbContext.AddRange(cartItems);
|
dbContext.AddRange(cartItems);
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -105,17 +93,17 @@ namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var context = new DefaultHttpContext();
|
var context = new DefaultHttpContext();
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
|
|
||||||
// AddressAndPayment action reads the Promo code from FormCollection.
|
// AddressAndPayment action reads the Promo code from FormCollection.
|
||||||
context.Request.Form =
|
context.Request.Form =
|
||||||
new FormCollection(new Dictionary<string, StringValues>());
|
new FormCollection(new Dictionary<string, StringValues>());
|
||||||
|
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
controller.ControllerContext.HttpContext = context;
|
controller.ControllerContext.HttpContext = context;
|
||||||
|
|
||||||
// Do not need actual data for Order; the Order object will be checked for the reference equality.
|
// Do not need actual data for Order; the Order object will be checked for the reference equality.
|
||||||
var order = new Order();
|
var order = CreateOrder();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = await controller.AddressAndPayment(dbContext, order, CancellationToken.None);
|
var result = await controller.AddressAndPayment(dbContext, order, CancellationToken.None);
|
||||||
|
|
@ -135,12 +123,12 @@ namespace MusicStore.Controllers
|
||||||
var context = new DefaultHttpContext();
|
var context = new DefaultHttpContext();
|
||||||
context.Request.Form =
|
context.Request.Form =
|
||||||
new FormCollection(new Dictionary<string, StringValues>());
|
new FormCollection(new Dictionary<string, StringValues>());
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
|
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
controller.ControllerContext.HttpContext = context;
|
controller.ControllerContext.HttpContext = context;
|
||||||
|
|
||||||
var order = new Order();
|
var order = CreateOrder();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = await controller.AddressAndPayment(dbContext, order, new CancellationToken(true));
|
var result = await controller.AddressAndPayment(dbContext, order, new CancellationToken(true));
|
||||||
|
|
@ -157,11 +145,11 @@ namespace MusicStore.Controllers
|
||||||
public async Task AddressAndPayment_ReturnsOrderIfInvalidOrderModel()
|
public async Task AddressAndPayment_ReturnsOrderIfInvalidOrderModel()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
controller.ModelState.AddModelError("a", "ModelErrorA");
|
controller.ModelState.AddModelError("a", "ModelErrorA");
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
|
|
||||||
var order = new Order();
|
var order = CreateOrder();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = await controller.AddressAndPayment(dbContext, order, CancellationToken.None);
|
var result = await controller.AddressAndPayment(dbContext, order, CancellationToken.None);
|
||||||
|
|
@ -174,6 +162,22 @@ namespace MusicStore.Controllers
|
||||||
Assert.Same(order, viewResult.ViewData.Model);
|
Assert.Same(order, viewResult.ViewData.Model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Order CreateOrder(int orderId = 100, string userName = "TestUserA")
|
||||||
|
=> new Order
|
||||||
|
{
|
||||||
|
OrderId = orderId,
|
||||||
|
Username = userName,
|
||||||
|
FirstName = "Macavity",
|
||||||
|
LastName = "Clark",
|
||||||
|
Address = "11 Meadow Drive",
|
||||||
|
City = "Healing",
|
||||||
|
State = "IA",
|
||||||
|
PostalCode = "DN37 7RU",
|
||||||
|
Country = "USK",
|
||||||
|
Phone = "555 887876",
|
||||||
|
Email = "mc@sample.com"
|
||||||
|
};
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Complete_ReturnsOrderIdIfValid()
|
public async Task Complete_ReturnsOrderIdIfValid()
|
||||||
{
|
{
|
||||||
|
|
@ -187,16 +191,11 @@ namespace MusicStore.Controllers
|
||||||
User = new ClaimsPrincipal(new ClaimsIdentity(claims)),
|
User = new ClaimsPrincipal(new ClaimsIdentity(claims)),
|
||||||
};
|
};
|
||||||
|
|
||||||
var dbContext =
|
var dbContext = _fixture.Context;
|
||||||
_serviceProvider.GetRequiredService<MusicStoreContext>();
|
dbContext.Add(CreateOrder(orderId, userName));
|
||||||
dbContext.Add(new Order()
|
|
||||||
{
|
|
||||||
OrderId = orderId,
|
|
||||||
Username = userName
|
|
||||||
});
|
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -215,10 +214,9 @@ namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var invalidOrderId = 100;
|
var invalidOrderId = 100;
|
||||||
var dbContext =
|
var dbContext = _fixture.Context;
|
||||||
_serviceProvider.GetRequiredService<MusicStoreContext>();
|
|
||||||
|
|
||||||
var controller = new CheckoutController(_serviceProvider.GetService<ILogger<CheckoutController>>());
|
var controller = new CheckoutController(_fixture.ServiceProvider.GetService<ILogger<CheckoutController>>());
|
||||||
controller.ControllerContext.HttpContext = new DefaultHttpContext();
|
controller.ControllerContext.HttpContext = new DefaultHttpContext();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -233,10 +231,21 @@ namespace MusicStore.Controllers
|
||||||
private static CartItem[] CreateTestCartItems(string cartId, decimal itemPrice, int numberOfItem)
|
private static CartItem[] CreateTestCartItems(string cartId, decimal itemPrice, int numberOfItem)
|
||||||
{
|
{
|
||||||
var albums = Enumerable.Range(1, 10).Select(n =>
|
var albums = Enumerable.Range(1, 10).Select(n =>
|
||||||
new Album()
|
new Album
|
||||||
{
|
{
|
||||||
AlbumId = n,
|
AlbumId = n,
|
||||||
Price = itemPrice,
|
Price = itemPrice,
|
||||||
|
Title = "Greatest Hits",
|
||||||
|
Artist = new Artist
|
||||||
|
{
|
||||||
|
ArtistId = 1,
|
||||||
|
Name = "Kung Fu Kenny"
|
||||||
|
},
|
||||||
|
Genre = new Genre
|
||||||
|
{
|
||||||
|
GenreId = 1,
|
||||||
|
Name = "Rap"
|
||||||
|
}
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
var cartItems = Enumerable.Range(1, numberOfItem).Select(n =>
|
var cartItems = Enumerable.Range(1, numberOfItem).Select(n =>
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,27 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Mvc.ViewComponents;
|
using Microsoft.AspNetCore.Mvc.ViewComponents;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Components
|
namespace MusicStore.Components
|
||||||
{
|
{
|
||||||
public class GenreMenuComponentTest
|
public class GenreMenuComponentTest : IClassFixture<SqliteInMemoryFixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly SqliteInMemoryFixture _fixture;
|
||||||
|
|
||||||
public GenreMenuComponentTest()
|
public GenreMenuComponentTest(SqliteInMemoryFixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task GenreMenuComponent_Returns_NineGenres()
|
public async Task GenreMenuComponent_Returns_NineGenres()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var genreMenuComponent = new GenreMenuComponent(dbContext);
|
var genreMenuComponent = new GenreMenuComponent(dbContext);
|
||||||
|
|
||||||
PopulateData(dbContext);
|
PopulateData(dbContext);
|
||||||
|
|
@ -50,7 +39,7 @@ namespace MusicStore.Components
|
||||||
|
|
||||||
private static void PopulateData(MusicStoreContext context)
|
private static void PopulateData(MusicStoreContext context)
|
||||||
{
|
{
|
||||||
var genres = Enumerable.Range(1, 10).Select(n => new Genre { GenreId = n });
|
var genres = Enumerable.Range(1, 10).Select(n => new Genre { GenreId = n, Name = $"G{n}" });
|
||||||
|
|
||||||
context.AddRange(genres);
|
context.AddRange(genres);
|
||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
|
|
|
||||||
|
|
@ -12,22 +12,14 @@ using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Controllers
|
namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class HomeControllerTest
|
public class HomeControllerTest : IClassFixture<SqliteInMemoryFixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly SqliteInMemoryFixture _fixture;
|
||||||
|
|
||||||
public HomeControllerTest()
|
public HomeControllerTest(SqliteInMemoryFixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -50,8 +42,8 @@ namespace MusicStore.Controllers
|
||||||
public async Task Index_GetsSixTopAlbums()
|
public async Task Index_GetsSixTopAlbums()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var cache = _serviceProvider.GetRequiredService<IMemoryCache>();
|
var cache = _fixture.ServiceProvider.GetRequiredService<IMemoryCache>();
|
||||||
var controller = new HomeController(new TestAppSettings());
|
var controller = new HomeController(new TestAppSettings());
|
||||||
PopulateData(dbContext);
|
PopulateData(dbContext);
|
||||||
|
|
||||||
|
|
@ -116,12 +108,13 @@ namespace MusicStore.Controllers
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
var albums = Enumerable.Range(1, 10).Select(n =>
|
var albums = Enumerable.Range(1, 10).Select(n =>
|
||||||
new Album()
|
new Album
|
||||||
{
|
{
|
||||||
Artist = artists[n - 1],
|
Artist = artists[n - 1],
|
||||||
ArtistId = n,
|
ArtistId = n,
|
||||||
Genre = generes[n - 1],
|
Genre = generes[n - 1],
|
||||||
GenreId = n,
|
GenreId = n,
|
||||||
|
Title = "Greatest Hits",
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
return albums;
|
return albums;
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
|
|
@ -15,37 +13,14 @@ using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Controllers
|
namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class ManageControllerTest
|
public class ManageControllerTest : IClassFixture<ManageControllerTest.Fixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly Fixture _fixture;
|
||||||
|
|
||||||
public ManageControllerTest()
|
public ManageControllerTest(Fixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
|
|
||||||
services.AddOptions();
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
|
||||||
.AddEntityFrameworkStores<MusicStoreContext>();
|
|
||||||
|
|
||||||
services.AddMvc();
|
|
||||||
services.AddSingleton<IAuthenticationService, NoOpAuth>();
|
|
||||||
services.AddLogging();
|
|
||||||
|
|
||||||
// IHttpContextAccessor is required for SignInManager, and UserManager
|
|
||||||
var context = new DefaultHttpContext();
|
|
||||||
services.AddSingleton<IHttpContextAccessor>(
|
|
||||||
new HttpContextAccessor()
|
|
||||||
{
|
|
||||||
HttpContext = context,
|
|
||||||
});
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -56,19 +31,19 @@ namespace MusicStore.Controllers
|
||||||
var phone = "abcdefg";
|
var phone = "abcdefg";
|
||||||
var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, userId) };
|
var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, userId) };
|
||||||
|
|
||||||
var userManager = _serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
var userManager = _fixture.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
|
||||||
var userManagerResult = await userManager.CreateAsync(
|
var userManagerResult = await userManager.CreateAsync(
|
||||||
new ApplicationUser { Id = userId, UserName = "Test", TwoFactorEnabled = true, PhoneNumber = phone },
|
new ApplicationUser { Id = userId, UserName = "Test", TwoFactorEnabled = true, PhoneNumber = phone },
|
||||||
"Pass@word1");
|
"Pass@word1");
|
||||||
Assert.True(userManagerResult.Succeeded);
|
Assert.True(userManagerResult.Succeeded);
|
||||||
|
|
||||||
var signInManager = _serviceProvider.GetRequiredService<SignInManager<ApplicationUser>>();
|
var signInManager = _fixture.ServiceProvider.GetRequiredService<SignInManager<ApplicationUser>>();
|
||||||
|
|
||||||
var httpContext = _serviceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext;
|
var httpContext = _fixture.ServiceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext;
|
||||||
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims));
|
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims));
|
||||||
httpContext.RequestServices = _serviceProvider;
|
httpContext.RequestServices = _fixture.ServiceProvider;
|
||||||
|
|
||||||
var schemeProvider = _serviceProvider.GetRequiredService<IAuthenticationSchemeProvider>();
|
var schemeProvider = _fixture.ServiceProvider.GetRequiredService<IAuthenticationSchemeProvider>();
|
||||||
|
|
||||||
var controller = new ManageController(userManager, signInManager, schemeProvider);
|
var controller = new ManageController(userManager, signInManager, schemeProvider);
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
@ -117,5 +92,34 @@ namespace MusicStore.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Fixture : SqliteInMemoryFixture
|
||||||
|
{
|
||||||
|
public override IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services = base.ConfigureServices(services);
|
||||||
|
|
||||||
|
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().Build());
|
||||||
|
services.AddOptions();
|
||||||
|
|
||||||
|
|
||||||
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
|
.AddEntityFrameworkStores<MusicStoreContext>();
|
||||||
|
|
||||||
|
services.AddMvc();
|
||||||
|
services.AddSingleton<IAuthenticationService, NoOpAuth>();
|
||||||
|
services.AddLogging();
|
||||||
|
|
||||||
|
|
||||||
|
// IHttpContextAccessor is required for SignInManager, and UserManager
|
||||||
|
var context = new DefaultHttpContext();
|
||||||
|
services.AddSingleton<IHttpContextAccessor>(
|
||||||
|
new HttpContextAccessor()
|
||||||
|
{
|
||||||
|
HttpContext = context,
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,62 +3,49 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Test
|
namespace MusicStore.Test
|
||||||
{
|
{
|
||||||
public class ShoppingCartTest : IClassFixture<ShoppingCartFixture>
|
public class ShoppingCartTest : IClassFixture<SqliteInMemoryFixture>
|
||||||
{
|
{
|
||||||
private readonly ShoppingCartFixture _fixture;
|
private readonly SqliteInMemoryFixture _fixture;
|
||||||
|
|
||||||
public ShoppingCartTest(ShoppingCartFixture fixture)
|
public ShoppingCartTest(SqliteInMemoryFixture fixture)
|
||||||
{
|
{
|
||||||
_fixture = fixture;
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ComputesTotal()
|
public async Task ComputesTotal()
|
||||||
{
|
{
|
||||||
var cartId = Guid.NewGuid().ToString();
|
var cartId = Guid.NewGuid().ToString();
|
||||||
using (var db = _fixture.CreateContext())
|
var db = _fixture.Context;
|
||||||
{
|
var a = db.Albums.Add(
|
||||||
var a = db.Albums.Add(
|
new Album
|
||||||
new Album
|
{
|
||||||
|
AlbumId = 1,
|
||||||
|
Title = "Greatest Hits",
|
||||||
|
Price = 15.99m,
|
||||||
|
Artist = new Artist
|
||||||
{
|
{
|
||||||
Price = 15.99m
|
ArtistId = 1,
|
||||||
}).Entity;
|
Name = "Kung Fu Kenny"
|
||||||
|
},
|
||||||
|
Genre = new Genre
|
||||||
|
{
|
||||||
|
GenreId = 1,
|
||||||
|
Name = "Rap"
|
||||||
|
}
|
||||||
|
}).Entity;
|
||||||
|
|
||||||
db.CartItems.Add(new CartItem { Album = a, Count = 2, CartId = cartId });
|
db.CartItems.Add(new CartItem { Album = a, Count = 2, CartId = cartId });
|
||||||
|
|
||||||
db.SaveChanges();
|
db.SaveChanges();
|
||||||
|
|
||||||
Assert.Equal(31.98m, await ShoppingCart.GetCart(db, cartId).GetTotal());
|
Assert.Equal(31.98m, await ShoppingCart.GetCart(db, cartId).GetTotal());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShoppingCartFixture
|
|
||||||
{
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
|
|
||||||
public ShoppingCartFixture()
|
|
||||||
{
|
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
|
||||||
|
|
||||||
var services = new ServiceCollection();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual MusicStoreContext CreateContext()
|
|
||||||
=> _serviceProvider.GetRequiredService<MusicStoreContext>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,8 @@ using Microsoft.AspNetCore.Antiforgery;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.ObjectPool;
|
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using MusicStore.Models;
|
using MusicStore.Models;
|
||||||
using MusicStore.ViewModels;
|
using MusicStore.ViewModels;
|
||||||
|
|
@ -18,23 +16,14 @@ using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Controllers
|
namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class ShoppingCartControllerTest
|
public class ShoppingCartControllerTest : IClassFixture<ShoppingCartControllerTest.Fixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly Fixture _fixture;
|
||||||
|
|
||||||
public ShoppingCartControllerTest()
|
public ShoppingCartControllerTest(Fixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
services.AddMvc();
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -45,8 +34,8 @@ namespace MusicStore.Controllers
|
||||||
httpContext.Session = new TestSession();
|
httpContext.Session = new TestSession();
|
||||||
|
|
||||||
var controller = new ShoppingCartController(
|
var controller = new ShoppingCartController(
|
||||||
_serviceProvider.GetRequiredService<MusicStoreContext>(),
|
_fixture.Context,
|
||||||
_serviceProvider.GetService<ILogger<ShoppingCartController>>());
|
_fixture.ServiceProvider.GetService<ILogger<ShoppingCartController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -71,8 +60,8 @@ namespace MusicStore.Controllers
|
||||||
httpContext.Session.SetString("Session", "CartId_A");
|
httpContext.Session.SetString("Session", "CartId_A");
|
||||||
|
|
||||||
var controller = new ShoppingCartController(
|
var controller = new ShoppingCartController(
|
||||||
_serviceProvider.GetRequiredService<MusicStoreContext>(),
|
_fixture.Context,
|
||||||
_serviceProvider.GetService<ILogger<ShoppingCartController>>());
|
_fixture.ServiceProvider.GetService<ILogger<ShoppingCartController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -97,7 +86,7 @@ namespace MusicStore.Controllers
|
||||||
httpContext.Session = new TestSession();
|
httpContext.Session = new TestSession();
|
||||||
httpContext.Session.SetString("Session", cartId);
|
httpContext.Session.SetString("Session", cartId);
|
||||||
|
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var cartItems = CreateTestCartItems(
|
var cartItems = CreateTestCartItems(
|
||||||
cartId,
|
cartId,
|
||||||
itemPrice: 10,
|
itemPrice: 10,
|
||||||
|
|
@ -108,7 +97,7 @@ namespace MusicStore.Controllers
|
||||||
|
|
||||||
var controller = new ShoppingCartController(
|
var controller = new ShoppingCartController(
|
||||||
dbContext,
|
dbContext,
|
||||||
_serviceProvider.GetService<ILogger<ShoppingCartController>>());
|
_fixture.ServiceProvider.GetService<ILogger<ShoppingCartController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -134,14 +123,14 @@ namespace MusicStore.Controllers
|
||||||
httpContext.Session.SetString("Session", "CartId_A");
|
httpContext.Session.SetString("Session", "CartId_A");
|
||||||
|
|
||||||
// Creates the albums of AlbumId = 1 ~ 10.
|
// Creates the albums of AlbumId = 1 ~ 10.
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var albums = CreateTestAlbums(itemPrice: 10);
|
var albums = CreateTestAlbums(itemPrice: 10);
|
||||||
dbContext.AddRange(albums);
|
dbContext.AddRange(albums);
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
var controller = new ShoppingCartController(
|
var controller = new ShoppingCartController(
|
||||||
dbContext,
|
dbContext,
|
||||||
_serviceProvider.GetService<ILogger<ShoppingCartController>>());
|
_fixture.ServiceProvider.GetService<ILogger<ShoppingCartController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -172,7 +161,7 @@ namespace MusicStore.Controllers
|
||||||
httpContext.Session.SetString("Session", cartId);
|
httpContext.Session.SetString("Session", cartId);
|
||||||
|
|
||||||
// DbContext initialization
|
// DbContext initialization
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var cartItems = CreateTestCartItems(cartId, unitPrice, numberOfItem);
|
var cartItems = CreateTestCartItems(cartId, unitPrice, numberOfItem);
|
||||||
dbContext.AddRange(cartItems.Select(n => n.Album).Distinct());
|
dbContext.AddRange(cartItems.Select(n => n.Album).Distinct());
|
||||||
dbContext.AddRange(cartItems);
|
dbContext.AddRange(cartItems);
|
||||||
|
|
@ -183,7 +172,7 @@ namespace MusicStore.Controllers
|
||||||
httpContext.Features.Set<IServiceProvidersFeature>(serviceProviderFeature);
|
httpContext.Features.Set<IServiceProvidersFeature>(serviceProviderFeature);
|
||||||
|
|
||||||
// AntiForgery initialization
|
// AntiForgery initialization
|
||||||
serviceProviderFeature.RequestServices = _serviceProvider;
|
serviceProviderFeature.RequestServices = _fixture.ServiceProvider;
|
||||||
var antiForgery = serviceProviderFeature.RequestServices.GetRequiredService<IAntiforgery>();
|
var antiForgery = serviceProviderFeature.RequestServices.GetRequiredService<IAntiforgery>();
|
||||||
var tokens = antiForgery.GetTokens(httpContext);
|
var tokens = antiForgery.GetTokens(httpContext);
|
||||||
|
|
||||||
|
|
@ -196,7 +185,7 @@ namespace MusicStore.Controllers
|
||||||
// Cotroller initialization
|
// Cotroller initialization
|
||||||
var controller = new ShoppingCartController(
|
var controller = new ShoppingCartController(
|
||||||
dbContext,
|
dbContext,
|
||||||
_serviceProvider.GetService<ILogger<ShoppingCartController>>());
|
_fixture.ServiceProvider.GetService<ILogger<ShoppingCartController>>());
|
||||||
controller.ControllerContext.HttpContext = httpContext;
|
controller.ControllerContext.HttpContext = httpContext;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -207,7 +196,7 @@ namespace MusicStore.Controllers
|
||||||
var viewModel = Assert.IsType<ShoppingCartRemoveViewModel>(jsonResult.Value);
|
var viewModel = Assert.IsType<ShoppingCartRemoveViewModel>(jsonResult.Value);
|
||||||
Assert.Equal(numberOfItem - 1, viewModel.CartCount);
|
Assert.Equal(numberOfItem - 1, viewModel.CartCount);
|
||||||
Assert.Equal((numberOfItem - 1) * 10, viewModel.CartTotal);
|
Assert.Equal((numberOfItem - 1) * 10, viewModel.CartTotal);
|
||||||
Assert.Equal(" has been removed from your shopping cart.", viewModel.Message);
|
Assert.Equal("Greatest Hits has been removed from your shopping cart.", viewModel.Message);
|
||||||
|
|
||||||
var cart = ShoppingCart.GetCart(dbContext, httpContext);
|
var cart = ShoppingCart.GetCart(dbContext, httpContext);
|
||||||
Assert.DoesNotContain((await cart.GetCartItems()), c => c.CartItemId == cartItemId);
|
Assert.DoesNotContain((await cart.GetCartItems()), c => c.CartItemId == cartItemId);
|
||||||
|
|
@ -232,11 +221,34 @@ namespace MusicStore.Controllers
|
||||||
private static Album[] CreateTestAlbums(decimal itemPrice)
|
private static Album[] CreateTestAlbums(decimal itemPrice)
|
||||||
{
|
{
|
||||||
return Enumerable.Range(1, 10).Select(n =>
|
return Enumerable.Range(1, 10).Select(n =>
|
||||||
new Album()
|
new Album
|
||||||
{
|
{
|
||||||
|
Title = "Greatest Hits",
|
||||||
AlbumId = n,
|
AlbumId = n,
|
||||||
Price = itemPrice,
|
Price = itemPrice,
|
||||||
|
Artist = new Artist
|
||||||
|
{
|
||||||
|
ArtistId = 1,
|
||||||
|
Name = "Kung Fu Kenny"
|
||||||
|
},
|
||||||
|
Genre = new Genre
|
||||||
|
{
|
||||||
|
GenreId = 1,
|
||||||
|
Name = "Rap"
|
||||||
|
}
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Fixture : SqliteInMemoryFixture
|
||||||
|
{
|
||||||
|
public override IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services = base.ConfigureServices(services);
|
||||||
|
|
||||||
|
services.AddMvc();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using MusicStore.Models;
|
||||||
|
|
||||||
|
namespace MusicStore
|
||||||
|
{
|
||||||
|
public class SqliteInMemoryFixture : IDisposable
|
||||||
|
{
|
||||||
|
private IServiceScope _serviceScope;
|
||||||
|
private SqliteConnection _connection;
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
_connection?.Close();
|
||||||
|
_connection?.Dispose();
|
||||||
|
_serviceScope?.Dispose();
|
||||||
|
_serviceScope= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IServiceCollection ConfigureServices(IServiceCollection services)
|
||||||
|
=> services
|
||||||
|
.AddMemoryCache()
|
||||||
|
.AddLogging()
|
||||||
|
.AddDbContext<MusicStoreContext>(b => b.UseSqlite(_connection));
|
||||||
|
|
||||||
|
public virtual IServiceProvider ServiceProvider
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_serviceScope == null)
|
||||||
|
{
|
||||||
|
_serviceScope = ConfigureServices(new ServiceCollection()).BuildServiceProvider().CreateScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _serviceScope.ServiceProvider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual MusicStoreContext Context
|
||||||
|
=> ServiceProvider.GetRequiredService<MusicStoreContext>();
|
||||||
|
|
||||||
|
public virtual void CreateDatabase()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
_connection = new SqliteConnection("Data Source=:memory:");
|
||||||
|
_connection.Open();
|
||||||
|
Context.Database.EnsureCreated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,29 +12,21 @@ using Xunit;
|
||||||
|
|
||||||
namespace MusicStore.Controllers
|
namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class StoreControllerTest
|
public class StoreControllerTest : IClassFixture<SqliteInMemoryFixture>
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly SqliteInMemoryFixture _fixture;
|
||||||
|
|
||||||
public StoreControllerTest()
|
public StoreControllerTest(SqliteInMemoryFixture fixture)
|
||||||
{
|
{
|
||||||
var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();
|
_fixture = fixture;
|
||||||
|
_fixture.CreateDatabase();
|
||||||
var services = new ServiceCollection();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddMemoryCache()
|
|
||||||
.AddLogging()
|
|
||||||
.AddDbContext<MusicStoreContext>(b => b.UseInMemoryDatabase("Scratch").UseInternalServiceProvider(efServiceProvider));
|
|
||||||
|
|
||||||
_serviceProvider = services.BuildServiceProvider();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Index_CreatesViewWithGenres()
|
public async Task Index_CreatesViewWithGenres()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
CreateTestGenres(numberOfGenres: 10, numberOfAlbums: 1, dbContext: dbContext);
|
CreateTestGenres(numberOfGenres: 10, numberOfAlbums: 1, dbContext: dbContext);
|
||||||
|
|
||||||
var controller = new StoreController(dbContext, new TestAppSettings());
|
var controller = new StoreController(dbContext, new TestAppSettings());
|
||||||
|
|
@ -56,7 +48,7 @@ namespace MusicStore.Controllers
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var controller = new StoreController(
|
var controller = new StoreController(
|
||||||
_serviceProvider.GetRequiredService<MusicStoreContext>(),
|
_fixture.Context,
|
||||||
new TestAppSettings());
|
new TestAppSettings());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -72,7 +64,7 @@ namespace MusicStore.Controllers
|
||||||
// Arrange
|
// Arrange
|
||||||
var genreName = "Genre 1";
|
var genreName = "Genre 1";
|
||||||
|
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
CreateTestGenres(numberOfGenres: 3, numberOfAlbums: 3, dbContext: dbContext);
|
CreateTestGenres(numberOfGenres: 3, numberOfAlbums: 3, dbContext: dbContext);
|
||||||
|
|
||||||
var controller = new StoreController(dbContext, new TestAppSettings());
|
var controller = new StoreController(dbContext, new TestAppSettings());
|
||||||
|
|
@ -97,11 +89,11 @@ namespace MusicStore.Controllers
|
||||||
// Arrange
|
// Arrange
|
||||||
var albumId = int.MinValue;
|
var albumId = int.MinValue;
|
||||||
var controller = new StoreController(
|
var controller = new StoreController(
|
||||||
_serviceProvider.GetRequiredService<MusicStoreContext>(),
|
_fixture.Context,
|
||||||
new TestAppSettings());
|
new TestAppSettings());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = await controller.Details(_serviceProvider.GetRequiredService<IMemoryCache>(), albumId);
|
var result = await controller.Details(_fixture.ServiceProvider.GetRequiredService<IMemoryCache>(), albumId);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.IsType<NotFoundResult>(result);
|
Assert.IsType<NotFoundResult>(result);
|
||||||
|
|
@ -113,10 +105,10 @@ namespace MusicStore.Controllers
|
||||||
// Arrange
|
// Arrange
|
||||||
var albumId = 1;
|
var albumId = 1;
|
||||||
|
|
||||||
var dbContext = _serviceProvider.GetRequiredService<MusicStoreContext>();
|
var dbContext = _fixture.Context;
|
||||||
var genres = CreateTestGenres(numberOfGenres: 3, numberOfAlbums: 3, dbContext: dbContext);
|
var genres = CreateTestGenres(numberOfGenres: 3, numberOfAlbums: 3, dbContext: dbContext);
|
||||||
|
|
||||||
var cache = _serviceProvider.GetRequiredService<IMemoryCache>();
|
var cache = _fixture.ServiceProvider.GetRequiredService<IMemoryCache>();
|
||||||
|
|
||||||
var controller = new StoreController(dbContext, new TestAppSettings());
|
var controller = new StoreController(dbContext, new TestAppSettings());
|
||||||
|
|
||||||
|
|
@ -148,31 +140,22 @@ namespace MusicStore.Controllers
|
||||||
artist.Name = "Artist1";
|
artist.Name = "Artist1";
|
||||||
|
|
||||||
var albums = Enumerable.Range(1, numberOfAlbums * numberOfGenres).Select(n =>
|
var albums = Enumerable.Range(1, numberOfAlbums * numberOfGenres).Select(n =>
|
||||||
new Album()
|
new Album
|
||||||
{
|
{
|
||||||
AlbumId = n,
|
AlbumId = n,
|
||||||
Artist = artist,
|
Artist = artist,
|
||||||
ArtistId = artist.ArtistId
|
ArtistId = artist.ArtistId,
|
||||||
|
Title = "Greatest Hits",
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var generes = Enumerable.Range(1, numberOfGenres).Select(n =>
|
var generes = Enumerable.Range(1, numberOfGenres).Select(n =>
|
||||||
new Genre()
|
new Genre
|
||||||
{
|
{
|
||||||
Albums = albums.Where(i => i.AlbumId % numberOfGenres == n - 1).ToList(),
|
Albums = albums.Where(i => i.AlbumId % numberOfGenres == n - 1).ToList(),
|
||||||
GenreId = n,
|
GenreId = n,
|
||||||
Name = "Genre " + n
|
Name = "Genre " + n
|
||||||
});
|
});
|
||||||
|
|
||||||
var artis = Enumerable.Range(1, numberOfGenres).Select(n =>
|
|
||||||
new Genre()
|
|
||||||
{
|
|
||||||
Albums = albums.Where(i => i.AlbumId % numberOfGenres == n - 1).ToList(),
|
|
||||||
GenreId = n,
|
|
||||||
Name = "Genre " + n,
|
|
||||||
});
|
|
||||||
|
|
||||||
dbContext.Add(artist);
|
|
||||||
dbContext.AddRange(albums);
|
|
||||||
dbContext.AddRange(generes);
|
dbContext.AddRange(generes);
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue