Entity Framework 5 - How to change connection string for unit testing?
This is my first foray into Entity Framework, and I have a working project
with EF5 and the repository pattern. I want to do integration testing
against a live DB. I made a snapshot of my existing production database
and wrote a stored procedure to recreate a fresh snapshot every time I
want to run tests. My question is how to I switch my context to this
database snapshot when "in unit testing 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 it stands now, I have my DbContext with the entities 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
}
What I think I need to do is change the base("name=ReportingDbContext")
into ("name=TestingDbContext"), but given how I have my
Repository/UnitOfWork setup I'm not seeing how I can do so. The issue 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 has been great is that I can do a bunch of stuff to all my
repositories and save it in one shot without having a bunch of contexts
floating around to synchronize. It may or may not be relevant to this
question, but this is how my UnitOfWork uses the repository. There is only
1 repository class, but it can be fed with any entity type needed:
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 of where this magic is used is inside my WCF service. This is
where I want to actually run through an integration test. A particular
method in my service initializes a unit of work and uses that do stuff.
The UnitOfWork creates a ReportingDbContext when it is new'd up, and this
ReportingDbContext in turn refers to the connection string of
"name=ReportingDbContext". After much reading, I think the answer is to
use an IoC container like Unity or Ninject (haven't used one before, but
I'd like to), and I'm stuck on how to implement IoC in this situation.
Here is an example method that I'm using in my WCF service that seems
rather hardcoded to the live database connection string:
public ComputerDTO GetComputerDetails(string hostname, string client)
{
// don't worry about the return type, it's 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'd like to keep my connection strings inside my app.config if at all
possible and be able to somehow switch to the testing connection string
during the [SetUp] part of my NUnit testing of the methods in my WCF
service.
Thanks! Bill
No comments:
Post a Comment