kkoziarski / grpc-dotnet-enterprise

.NET Core gRPC example with testable gRPC services
MIT License
47 stars 12 forks source link

GrpcServerApplicationFactoryBase does not replace/remove DbContextOptions<TContext> #1

Open whighsmith opened 3 years ago

whighsmith commented 3 years ago

Had to use the following services.Remove statements in order to completely replace my original DbContext with one that uses InMemoryDatabase.

var registeredServiceDescriptor = services.FirstOrDefault(s => s.ServiceType == typeof(TContext));
services.Remove(registeredServiceDescriptor);

var dbContextOptionsDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(DbContextOptions<TContext>));
services.Remove(dbContextOptionsDescriptor);

in

GrpcServerApplicationFactoryBase

awesome solution by the way.. thanks.

kkoziarski commented 3 years ago

@whighsmith could you take a look at last comment and check if this is what you did?

whighsmith commented 3 years ago

@kkoziarski Yes... except I also removed the call to

services.Replace(ServiceDescriptor.Singleton<TContext, TContext>());

since the call to services.Replace in this case only "Adds" a descriptor (.Remove isn't called internally) and the InMemory DbContext will be added in the subclass (implementation of) GrpcServerApplicationFactoryBase when this.ConfigureTestServices(builder, services); is called.

On another note, I have also removed the dependency on DbContext (which moves all above source code to the subclass) out of the base classes all together since this testing infrastructure will be used with microservices and each microservice will have its own database which could mean a microservice could have a persistence layer that does not use DbContext but some other persistence mechanism and database/storage technology.

whighsmith commented 3 years ago

@kkoziarski You can also do the following in the subclass:

var dbContextOptionsDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(DbContextOptions<MyDbContext>));
services.Remove(dbContextOptionsDescriptor);

services.AddSingleton<DbContextOptions<MyDbContext>>(ctx =>
{
    var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
    return optionsBuilder.UseInMemoryDatabase("IntegrationDatabase").Options;
});

since replacing DbContextOptions with the InMemoryDatabase option is what you are trying to achieve.

kkoziarski commented 3 years ago

@whighsmith all are good points. I'm happy to accept your PR when you create it. Otherwise I'll try to do it in an undefined future.