Entity Framework 5 - How to change the connection string for unit testing?

This is my first foray into the Entity Framework, and I have a working project with EF5 and a repository template. I want to conduct integration testing with a live database. I took a snapshot of my existing production database and wrote a stored procedure to recreate a new snapshot every time I want to run tests. My question is how to switch my context to this database snapshot when "in unit test mode"? In my app.config, I have both my live and test connection strings as such:

<connectionStrings> <add name="ReportingDbContext" connectionString="Server=LiveServer;Database=UnifiedReporting;User Id='myuser';Password='mypass';Trusted_Connection=False" providerName="System.Data.SqlClient" /> <add name="TestingDbContext" connectionString="Server=LiveServer;Database=UnifiedReportingSnapshot;User Id='myuser';Password='mypass';Trusted_Connection=False" providerName="System.Data.SqlClient" /> </connectionStrings> 

As of now, I have my own DbContext with objects that I want to use as follows:

 public class ReportingDbContext : DbContext { public ReportingDbContext() : base("name=ReportingDbContext") // as per my app.config { } // inventory public DbSet<ComputerEntity> Computers { get; set; } public DbSet<NetworkAdapterEntity> NetworkAdapters { get; set; } // ... plus a whole bunch more } 

I think I need to change the base ("name = ReportingDbContext") to ("name = TestingDbContext"), but given how I have my repository / UnitOfWork setup, I don’t see how I can do this, The problem may be here in my UnitOfWork:

 public interface IUnitOfWork : IDisposable { void Commit(); // inventory IRepository<ComputerEntity> Computers { get; } IRepository<NetworkAdapterEntity> NetworkAdapters { get; } // ... plus a bunch more } public class UnitOfWork : IUnitOfWork { private readonly ReportingDbContext _dbContext = null; public UnitOfWork() { _dbContext = new ReportingDbContext(); } public void Commit() { _dbContext.SaveChanges(); } // Inventory public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }} public IRepository<NetworkAdapterEntity> NetworkAdapters { get { return new Repository<NetworkAdapterEntity>(_dbContext); } } // ... lots more } 

This UnitOfWork was great, so I can do a bunch of things for all my repositories and save it with one shot, without having a bunch of contexts floating around for synchronization. This may or may not be relevant for this question, but this is how my UnitOfWork uses the repository. There is only 1 repository class, but it can be loaded with any type of entity:

 public interface IRepository<T> where T : class { IQueryable<T> GetAll(); IQueryable<T> Find(Expression<Func<T, bool>> predicate); T GetById(int id); void Remove(T entity); void Add(T newEntity); } public class Repository<T> : IRepository<T> where T : class { protected DbContext DbContext { get; set; } protected DbSet<T> DbSet { get; set; } public Repository(DbContext dbContext) { if (dbContext == null) { throw new ArgumentNullException("dbContext"); } DbContext = dbContext; DbSet = DbContext.Set<T>(); } public IQueryable<T> GetAll() { return DbSet; } // ... more implementation of the interface, nothing fancy } 

The endpoint for using this magic is inside my WCF service. Here I want to actually pass the integration test. In my service, a special method initializes a unit of work and uses it. UnitOfWork creates a ReportingDbContext when it is updated, and this ReportingDbContext, in turn, refers to the connection string "name = ReportingDbContext". After a lot of reading, I think the answer is to use an IoC container such as Unity or Ninject (not previously used, but I would like to), and I was fixated on how to implement IoC in this situation. Here is an example that I use in my WCF service, which seems pretty tightly tied to the database connection string:

 public ComputerDTO GetComputerDetails(string hostname, string client) { // don't worry about the return type, it defined elsewhere using (var uoW = new UnitOfWork()) { var repo = uoW.Computers; var computer = repo.Find(x => x.Hostname == hostname && x.CompanyEntity.Name == client).FirstOrDefault(); // do stuff } } 

I would like to keep my connection strings inside my app.config, if at all possible, and be able to somehow switch to the connection test string during the [SetUp] part of my testing of NUnit methods in my WCF service.

+4
source share
1 answer

I always use a separate unit test project with my own App.config. The connection string has the same name as the main application, but the connection to the database is different.

When running unit test, for example. from inside Visual Studio, the unit test runner runs in the background, which is nothing more than a regular application with its own app.config configuration.

You can run and delete contexts for each test. Most unit test frameworks have attributes for marking methods as installation / disassembly tools that can either run on test equipment or on a test. You can initialize the IoC container in the setup of the test device ( [TestFixtureSetUp] in NUnit) and the context in the test setup ( [SetUp] in NUnit).

In some scenarios, we use scripts to ensure and restore the state of the database, but for most tests we run TransactionScope in the test setup and delete it (without committing) in test mode. This conveniently cancels any changes made in the test, but the database changes made in the tests are real.

+3
source

Source: https://habr.com/ru/post/1501351/


All Articles