I have a base context class that is derived from DbContext:
public abstract class BaseContext : DbContext { static BaseContext() { } protected BaseContext() : base("name=FrameworkOneDatabase") { } }Then some bounded contexts. Below is one of them:
public class ArticleBoundContext : BaseContext { public ArticleBoundContext() { } public virtual DbSet<Article> Article { get; set; } public virtual DbSet<User> Submitter { get; set; } }Also a basic service class to help me calling CRUD operations on any bounded context:
public class CRUDService { private BaseContext _context; public CRUDService(BaseContext context) { this._context = context; } public void Insert(dynamic entityObject) { dynamic dbset = GetDbSetFromObject(entityObject); entityObject.ObjectState = ObjectState.Added; dbset.Add(entityObject); _context.ApplyStateChanges(); } public void InsertOrUpdate(dynamic entityObject) { dynamic dbset = GetDbSetFromObject(entityObject); dbset.Attach(entityObject); _context.ApplyStateChanges(); } public void Delete(dynamic entityObject) { dynamic dbset = GetDbSetFromObject(entityObject); dbset.Remove(entityObject); } public async Task<int> Commit() { var result = await _context.SaveChangesAsync(); return result; } public void Dispose() { _context.Dispose(); } private dynamic GetDbSetFromObject(dynamic entityObject) { // if dynamicproxies wrapper is used then get the base object System.Type objectType = entityObject.GetType(); if (objectType.Namespace == "System.Data.Entity.DynamicProxies") { objectType = objectType.BaseType; } var dbset = (from p in _context.GetType().GetProperties() where p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) let entityType = p.PropertyType.GetGenericArguments().First() where objectType == entityType select p.GetValue(_context)).FirstOrDefault(); if (dbset == null) { throw new System.ArgumentException("object type does not exist in the context"); } return dbset; } }The class has methods accepting an object then will find its corresponding DbSet
Then I can use all of the classes and structure above to do something like in the tests below:
[TestClass] public class CRUDServiceTest { private ArticleBoundContext _context; private CRUDService _service; public CRUDServiceTest() { _context = new ArticleBoundContext(); _service = new CRUDService(_context); } [TestMethod] public async Task CanInsertArticle() { Article article = new Article { Title = "title test " + DateTime.Now.ToString("HH:mm:ss"), Description = "desc", Url = "test.com", ObjectState = ObjectState.Added }; article.Submitter = new User { Firstname = "first " + DateTime.Now.ToString("HH:mm:ss"), Lastname = "last", ObjectState = ObjectState.Added }; _service.Insert(article); var insert = await _service.Commit(); Assert.IsTrue(insert > 0); } [TestMethod] public async Task CanUpdateArticle() { Article article = _context.Article.FirstOrDefault(); article.Title = "UPDATED TITLE " + DateTime.Now.ToString("HH:mm:ss"); article.Description = "UPDATED DESCRIPTION"; article.ObjectState = ObjectState.Modified; _service.InsertOrUpdate(article); var update = await _service.Commit(); Assert.IsTrue(update > 0); } [TestMethod] public async Task CanUpdateSubmitter() { var article = _context.Article.FirstOrDefault(); article.Submitter.Firstname = "UPDATED FIRSTNAME " + DateTime.Now.ToString("HH:mm:ss"); article.Submitter.Lastname = "UPDATED LASTNAME " + DateTime.Now.ToString("HH:mm:ss"); article.Submitter.ObjectState = ObjectState.Modified; _service.InsertOrUpdate(article); var update = await _service.Commit(); Assert.IsTrue(update > 0); } [TestMethod] public async Task CanUpdateSubmitter_2() { var submitter = _context.Submitter.FirstOrDefault(); submitter.Firstname = "UPDATED FIRSTNAME " + DateTime.Now.ToString("HH:mm:ss"); submitter.Lastname = "UPDATED LASTNAME " + DateTime.Now.ToString("HH:mm:ss"); submitter.ObjectState = ObjectState.Modified; _service.InsertOrUpdate(submitter); var update = await _service.Commit(); Assert.IsTrue(update > 0); } [TestMethod] public async Task CanDeleteArticle() { var article = _context.Article.FirstOrDefault(); _service.Delete(article); var result = await _service.Commit(); Assert.IsTrue(result > 0); } [TestMethod] public async Task CanInsertAndDeleteSubmitter() { var submitter = new User(); submitter.Firstname = "firstname " +DateTime.Now.ToString("HH:mm:ss"); submitter.Lastname = "lastname " + DateTime.Now.ToString("HH:mm:ss"); _service.Insert(submitter); var result = await _service.Commit(); Assert.IsTrue(result > 0); var insertedSubmitter = await _context.Submitter.FindAsync(submitter.Id); Assert.IsTrue(insertedSubmitter.Firstname == submitter.Firstname && insertedSubmitter.Lastname == submitter.Lastname); _service.Delete(submitter); result = await _service.Commit(); Assert.IsTrue(result > 0); } [TestMethod] public async Task ThrowExceptionWhenInsertingWrongObject() { try { int test = 5; _service.Insert(test); var insert = await _service.Commit(); } catch (Exception ex) { Assert.IsInstanceOfType(ex, typeof(System.ArgumentException)); } } }