Итак, я настраиваю API в. NET Core 3.1, который работает нормально, когда я запускаю его локально, но когда я запускаю свой проект xUnit, я получаю эту System.InvalidOperationException : Scheme already exists: Identity.Application
ошибку.
Теперь я начал поискать в Google для этого, и похоже, что основным решением обычно является удаление AddDefaultIdentity
, чтобы либо остановить cla sh с помощью IdentityHostingStartup
, либо предотвратить IdentityHostintgStartup.cs , чтобы вызвать некоторое перекрытие.
Для меня я не использую AddDefaultIdentity
и не вижу генерирования IdentityHostintgStartup.cs
, поэтому я не совсем уверен, в чем заключается сделка.
Вот мой Регистрация службы идентификации, которая добавляется в Startup
public static class ServiceExtensions
{
public static void AddIdentityInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
if (configuration.GetValue<bool>("UseInMemoryDatabase"))
{
services.AddDbContext<IdentityDbContext>(options =>
options.UseInMemoryDatabase("IdentityDb"));
}
else
{
services.AddDbContext<IdentityDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("IdentityConnection"),
b => b.MigrationsAssembly(typeof(IdentityDbContext).Assembly.FullName)));
}
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<IdentityDbContext>().AddDefaultTokenProviders();
#region Services
services.AddScoped<IAccountService, AccountService>();
#endregion
services.Configure<IdentityOptions>(options =>
{
options.User.RequireUniqueEmail = true;
options.Password.RequiredLength = 12;
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = false;
options.Password.RequireNonAlphanumeric = false;
});
services.Configure<JwtSettings>(configuration.GetSection("JwtSettings"));
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.RequireHttpsMetadata = false;
o.SaveToken = false;
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
ValidIssuer = configuration["JwtSettings:Issuer"],
ValidAudience = configuration["JwtSettings:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtSettings:Key"]))
};
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.NoResult();
c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
return c.Response.WriteAsync(c.Exception.ToString());
},
OnChallenge = context =>
{
context.HandleResponse();
context.Response.StatusCode = 401;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(new Response<string>("You are not Authorized"));
return context.Response.WriteAsync(result);
},
OnForbidden = context =>
{
context.Response.StatusCode = 403;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(new Response<string>("You are not authorized to access this resource"));
return context.Response.WriteAsync(result);
},
};
});
}
}
А вот моя фабрика для моих интеграционных тестов
public class CustomWebApplicationFactory : WebApplicationFactory<Startup>
{
// checkpoint for respawn to clear the database when spenning up each time
private static Checkpoint checkpoint = new Checkpoint
{
};
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Testing");
builder.ConfigureServices(services =>
{
services.AddEntityFrameworkInMemoryDatabase();
// Create a new service provider.
var provider = services
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
// Add a database context (ApplicationDbContext) using an in-memory
// database for testing.
services.AddDbContext<ValueToReplaceDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryDbForTesting");
options.UseInternalServiceProvider(provider);
});
services.AddDbContext<IdentityDbContext>(options =>
{
options.UseInMemoryDatabase("Identity");
options.UseInternalServiceProvider(provider);
});
// Build the service provider.
var sp = services.BuildServiceProvider();
// Create a scope to obtain a reference to the database
// context (ApplicationDbContext).
using (var scope = sp.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<ValueToReplaceDbContext>();
/* var loggerFactory = scopedServices.GetRequiredService<ILoggerFactory>();
var logger = scopedServices
.GetRequiredService<ILogger<ApiTestFixture>>();*/
// Ensure the database is created.
db.Database.EnsureCreated();
try
{
// Seed the database with test data.
//ValueToReplaceDbContextSeed.SeedAsync(db, loggerFactory).Wait();
// seed sample user data
/*var userManager = scopedServices.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = scopedServices.GetRequiredService<RoleManager<IdentityRole>>();
AppIdentityDbContextSeed.SeedAsync(userManager, roleManager).Wait();*/
}
catch (Exception ex)
{
//logger.LogError(ex, $"An error occurred seeding the " +
// "database with test messages. Error: {ex.Message}");
}
}
});
}
public HttpClient GetAnonymousClient()
{
return CreateClient();
}
}