Skip to content

Commit 7b16ae7

Browse files
committed
Added DbContext setup option to the EntityFrameworkCore package (#125)
1 parent 168b72f commit 7b16ae7

File tree

5 files changed

+151
-2
lines changed

5 files changed

+151
-2
lines changed

src/MyTested.AspNetCore.Mvc.Core/Builders/Controllers/ControllerServiceBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public IAndControllerBuilder<TController> WithServiceSetupFor<TService>(Action<T
2222
var serviceLifetime = TestServiceProvider.GetServiceLifetime<TService>();
2323
if (serviceLifetime != ServiceLifetime.Scoped)
2424
{
25-
throw new InvalidOperationException("This overload of the 'WithServiceSetupFor' method can be used only for services with scoped lifetime.");
25+
throw new InvalidOperationException("The 'WithServiceSetupFor' method can be used only for services with scoped lifetime.");
2626
}
2727

2828
scopedServiceSetup(this.HttpContext.RequestServices.GetService<TService>());
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Data
2+
{
3+
using System;
4+
using Microsoft.EntityFrameworkCore;
5+
6+
/// <summary>
7+
/// Used for building <see cref="DbContext"/>.
8+
/// </summary>
9+
public interface IDbContextBuilder
10+
{
11+
/// <summary>
12+
/// Sets initial values to the provided <see cref="DbContext"/> service.
13+
/// </summary>
14+
/// <typeparam name="TDbContext">Type of <see cref="DbContext"/> to set up.</typeparam>
15+
/// <param name="dbContextSetup">Action setting the <see cref="DbContext"/>.</param>
16+
void WithSetup<TDbContext>(Action<TDbContext> dbContextSetup)
17+
where TDbContext : DbContext;
18+
}
19+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Data
2+
{
3+
using System;
4+
using Base;
5+
using Contracts.Data;
6+
using Internal.Application;
7+
using Internal.TestContexts;
8+
using Microsoft.EntityFrameworkCore;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using Utilities.Validators;
11+
12+
/// <summary>
13+
/// Used for building <see cref="DbContext"/>.
14+
/// </summary>
15+
public class DbContextBuilder : BaseTestBuilder, IDbContextBuilder
16+
{
17+
/// <summary>
18+
/// Initializes a new instance of the <see cref="DbContextBuilder"/> class.
19+
/// </summary>
20+
/// <param name="testContext"><see cref="HttpTestContext"/> containing data about the currently executed assertion chain.</param>
21+
public DbContextBuilder(HttpTestContext testContext)
22+
: base(testContext)
23+
{
24+
}
25+
26+
/// <inheritdoc />
27+
public void WithSetup<TDbContext>(Action<TDbContext> dbContextSetup)
28+
where TDbContext : DbContext
29+
{
30+
CommonValidator.CheckForNullReference(dbContextSetup, nameof(dbContextSetup));
31+
32+
var serviceLifetime = TestServiceProvider.GetServiceLifetime<TDbContext>();
33+
if (serviceLifetime != ServiceLifetime.Scoped)
34+
{
35+
throw new InvalidOperationException("The 'WithSetup' method can be used only for services with scoped lifetime.");
36+
}
37+
38+
var dbContext = this.TestContext.HttpContext.RequestServices.GetRequiredService<TDbContext>();
39+
40+
dbContextSetup(dbContext);
41+
42+
dbContext.SaveChanges();
43+
}
44+
}
45+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
namespace MyTested.AspNetCore.Mvc
2+
{
3+
using System;
4+
using Builders.Contracts.Data;
5+
using Builders.Controllers;
6+
using Builders.Data;
7+
using Microsoft.EntityFrameworkCore;
8+
9+
/// <summary>
10+
/// Contains <see cref="DbContext"/> extension methods for <see cref="IControllerBuilder{TController}"/>.
11+
/// </summary>
12+
public static class ControllerBuilderEntityFrameworkCoreExtensions
13+
{
14+
/// <summary>
15+
/// Sets initial values to the <see cref="DbContext"/> on the tested controller.
16+
/// </summary>
17+
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
18+
/// <param name="controllerBuilder">Instance of <see cref="IControllerBuilder{TController}"/> type.</param>
19+
/// <param name="dbContextSetup">Action setting the <see cref="DbContext"/>.</param>
20+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
21+
public static IControllerBuilder<TController> WithDbContext<TController>(
22+
this IControllerBuilder<TController> controllerBuilder,
23+
Action<DbContext> dbContextSetup)
24+
where TController : class
25+
{
26+
var actualControllerBuilder = (ControllerBuilder<TController>)controllerBuilder;
27+
28+
actualControllerBuilder.WithServiceSetupFor<DbContext>(dbContext =>
29+
{
30+
dbContextSetup(dbContext);
31+
dbContext.SaveChanges();
32+
});
33+
34+
return actualControllerBuilder;
35+
}
36+
37+
/// <summary>
38+
/// Sets initial values to the <see cref="DbContext"/> on the tested controller.
39+
/// </summary>
40+
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
41+
/// <param name="controllerBuilder">Instance of <see cref="IControllerBuilder{TController}"/> type.</param>
42+
/// <param name="dbContextBuilder">Action setting the <see cref="DbContext"/> by using <see cref="IDbContextBuilder"/>.</param>
43+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
44+
public static IControllerBuilder<TController> WithDbContext<TController>(
45+
this IControllerBuilder<TController> controllerBuilder,
46+
Action<IDbContextBuilder> dbContextBuilder)
47+
where TController : class
48+
{
49+
var actualControllerBuilder = (ControllerBuilder<TController>)controllerBuilder;
50+
51+
dbContextBuilder(new DbContextBuilder(actualControllerBuilder.TestContext));
52+
53+
return actualControllerBuilder;
54+
}
55+
}
56+
}

test/MyTested.AspNetCore.Mvc.EntityFrameworkCore.Test/ServicesTests.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
public class ServicesTests
1313
{
1414
[Fact]
15-
public static void ReplaceDbContextShouldReplaceNonInMemoryDatabaseWithInMemoryScopedOne()
15+
public void ReplaceDbContextShouldReplaceNonInMemoryDatabaseWithInMemoryScopedOne()
1616
{
1717
var services = new ServiceCollection();
1818

@@ -21,6 +21,35 @@ public static void ReplaceDbContextShouldReplaceNonInMemoryDatabaseWithInMemoryS
2121

2222
services.ReplaceDbContext();
2323

24+
this.AssertCorrectDbContextAndOptions(services);
25+
}
26+
27+
[Fact]
28+
public void ReplaceDbContextShouldReplaceInMemoryDatabaseWithInMemoryScopedOne()
29+
{
30+
var services = new ServiceCollection();
31+
32+
services.AddDbContext<CustomDbContext>(options => options.UseInMemoryDatabase());
33+
34+
services.ReplaceDbContext();
35+
36+
this.AssertCorrectDbContextAndOptions(services);
37+
}
38+
39+
[Fact]
40+
public void ReplaceDbContextShouldNotAddDbContextIfMissing()
41+
{
42+
var services = new ServiceCollection();
43+
44+
services.ReplaceDbContext();
45+
46+
var serviceProvider = services.BuildServiceProvider();
47+
48+
Assert.Null(serviceProvider.GetService<DbContext>());
49+
}
50+
51+
private void AssertCorrectDbContextAndOptions(IServiceCollection services)
52+
{
2453
var serviceProvider = services.BuildServiceProvider();
2554

2655
var dbContextService = services.FirstOrDefault(s => s.ServiceType == typeof(CustomDbContext));

0 commit comments

Comments
 (0)