Unit Of Work and Repository inter dependency - repository-pattern

I have seen lots of posts (and debates!) about which way round UnitOfWork and Repository. One of the repository patterns I favor is the typed generic repository pattern, but I fear this had lead to some issues with clean code and testability. Take the following repository interface and generic class:
public interface IDataEntityRepository<T> : IDisposable where T : IDataEntity
{
// CRUD
int Create(T createObject);
// etc.
}
public class DataEntityRepository<T> : IDataEntityRepository<T> where T : class, IDataEntity
{
private IDbContext Context { get; set; }
public DataEntityRepository (IDbContext context)
{
Context = context;
}
private IDbSet<T> DbSet { get { return Context.Set<T>(); } }
public int Create(T CreateObject)
{
DbSet.Add(createObject);
}
// etc.
}
// where
public interface IDbContext
{
IDbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T readObject) where T : class;
int SaveChanges();
void Dispose();
}
So basically I am using the Context property in each pattern to gain access to the underlying context.
My problem is now this: when I create my unit of work, it will effectively be a wrapper of the context I need the repository to know about. So, if I have a Unit Of Work that declares the following:
public UserUnitOfWork(
IDataEntityRepository<User> userRepository,
IDataEntityRepository<Role> roleRepository)
{
_userRepository = userRepository;
_roleRepository = roleRepository;
}
private readonly IDataEntityRepository<User> _userRepository;
public IDataEntityRepository<User> UserRepository
{
get { return _userRepository; }
}
private readonly IDataEntityRepository<Role> _roleRepository;
public IDataEntityRepository<Role> RoleRepository
{
get { return _roleRepository; }
}
I have a problem with the fact that the two repositories I am passing in both need to be instantiated with the very Unit Of Work into which they are being passed. Obviously I could instantiate the repositories inside the constructor and pass in the "this" but that tightly couples my unit of work to a particular concrete instance of the repositories and makes unit testing that much harder.
I would be interested to know if anyone else has headed down this path and hit the same wall. Both these patterns are new to me so I could well be doing something fundamentally wrong. Any ideas would be much appreciated!
UPDATE (response to #MikeSW)
Hi Mike, many thanks for your input. I am working with EF Code First but I wanted to abstract certain elements so I could switch to a different data source or ORM if required and because I am (trying!) to push myself down a TDD route and using Mocking and IOC. I think I have realised the hard way that certain elements cannot be unit tested in a pure sense but can have integration tests! I'd like to raise your point about Repositories working with business objects or viewmodels etc. Perhaps I have misunderstood but if I have what I see as my core business objects (POCOs), and I then want to use an ORM such as EF code first to wrap around those entities in order to create, and then interact with, the database (and, it's possible, I may re-use these entities within a ViewModel), I would expect a Repository to handle these entities directly in the context of some set of CRUD operations. The entities know nothing about the persistence layer at all, neither would any ViewModel. My unit of work simply instantiates and holds the required repositories allowing a transaction commit to be performed (across multiple repositories but the same context/ session). What I have done in my solution is to remove the injection of an IDataEntityRepository ... etc. from the UnitOfWork constructor as this is a concrete class that must know about one and only one type of IDataEntityRepository it should be creating (in this case DataEntityRepository, which really should be bettered names as EFDataEntityRepository). I cannot unit test this per se because the whole unit logic would be to establish the repositories with a context (itself) to some database. It simply needs an integration test. Hope that makes sense?!

To avoid dependency on each repository in your Unit of Work, you could use a provider based on this contract:
public interface IRepositoryProvider
{
DbContext DbContext { get; set; }
IRepository<T> GetRepositoryForEntityType<T>() where T : class;
T GetRepository<T>(Func<DbContext, object> factory = null) where T : class;
void SetRepository<T>(T repository);
}
then you could inject it into your UoW that would look like this:
public class UserUnitOfWork: IUserUnitOfWork
{
public UserUnitOfWork(IRepositoryProvider repositoryProvider)
{
RepositoryProvider = repositoryProvider;
}
protected IDataEntityRepository<T> GetRepo<T>() where T : class
{
return RepositoryProvider.GetRepositoryForEntityType<T>();
}
public IDataEntityRepository<User> Users { get { return GetRepo<User>(); } }
public IDataEntityRepository<Role> Roles { get { return GetRepo<Role>(); } }
...

Apologies for the tardiness of my response - I have been trying out various approaches to this in the mean time. I have marked up the answers above because I agree with the comments made.
This is one of those questions where there is more than one answer and it's very much dependent upon the overall approach. Whilst I agree that EF effectively provides a ready-made unit of work pattern, my decision to create my own unit of work and repository layers was to be able to control access to the database entities.
Where I struggled was in the need to be able to inject a repository into a unit of work. What I realised though was that in the case of EF, my unit of work was effectively a thin wrapper around multiple repositories with a Commit (SaveChanges) method. It was not responsible for executing specific actions such as FindCustomer etc.
So I decided that a unit of work could be tightly coupled to its specific type of DataRepository pattern. To ensure I had a testable pattern, I introduced a service layer that provided the facade for executing particular actions such as CreateCustomer, FindCustomers etc. These services that accepted an IUnitOfWork constructor parameter which provided access to the repositories (as interfaces) as well as the Commit method.
I was then able to create fakes of both unit of work and/ or repositories for testing purposes. This just left me with the decision of what could be unit tested with fakes and what needed to be integration tested with the concrete instances.
And this also gives me the opportunity to control what actions are performed on the database and how they are performed.
I'm sure there are many ways to skin this particular cat but the goals of provided a clean interface that is testable have been just about met with this approach.
My thanks to g1ga and Mike for their input.

When using Entity Framework (EF) (which I assume you're using) you already have a generic repository IDbSet. It's useless to ad another layer on top just to call EF methods.
Also, a repository works with application objects (usually business objects, but they can be view models or objects state). If you're just using db entities, you kinda defeat the Repository pattern purpose ( to isolate the business bojects from the database). THe original pattern deals only with busines objects, but it is a useful pattern outside the business layer too.
The point is that EF entities are Persistence objects and have (or should have) no relation to your business objects. You want to use the repository pattern to 'translate' the busines objects to persistence objects and viceversa.
Sometimes it might happen that an application object (like a viewmodel) to be the same with a persistence entity (and in that case you can use directly EF objects) but that's a coincidence.
About Unit of Work (UoW), let's say that's tricky. Personally, I prefer to use the DDD (domain driven design) approach and consider that any business object (BO) sent to the repoistory is a UoW, so it will be wrapped in a transaction.
If I need to update multiple BOs, I'll use a message driven architecture to send commands to the relevant BOs. Of course, that's more complicated and requires to be at ease with the concept of eventual consistency but I'm not depending on a specific RDBMS.
If you know that you'll be using a specific RDBMS and that will never be changed, you could start a transaction and pass the associated connection to each repository, with a commit at the end (that will be the UoW). If you're in a web setting, it's even easier, start transaction when the request begins, commit when requests ends (you can use an ActionFilter for ASp.Net Mvc).
However this solution is tied up to one RDBMS, so it won't apply to a NoSql or any storage which doesn't support transactions. For those cases, the message driven way is the best.

Related

unit testing in web api with N tier without actual database calls

I am writing Unit Tests for My Web API application ,created with .net Core. I use MSTest with MOQ for mocking.
It has many layers as below.
Controller => Manager classes => Facade classes => Contract class
I am providing entity in controller that I have mocked.
[TestMethod]
public void InvoiceUpdateFinanceTest_Success()
{
var mock = mockFactory.OutstandingInvoicesDetailsMock();
dataController.InvoiceUpdateFinance(mock);
Assert.IsTrue(true);
}
Contract Class is creating DB connection instance and does database calls
Code sample in Contract Layer is as below
public class GradeWiseSlab : IMaintainContract
{
IDbConnection _db = new DBModel().InstanceCreation();
DynamicParameters dp = new DynamicParameters();
public MaintainContractEntities MaintainContractEntities { get; set; }
public void SaveData()
{
dp.Add("#N_VENDOR_ID", MaintainContractEntities.VendorId);
dp.Add("#N_CONTRACT_SUB_TYPE_ID", MaintainContractEntities.SubContractType);
dp.Add("#N_PAYMENT_TERM", MaintainContractEntities.PaymentTerm);
dp.Add("#S_TRANSACTION_CURRENCY", MaintainContractEntities.TransactionCurrency);
dp.Add("#S_DOC_NAME", MaintainContractEntities.DocNames);
dp.Add("#S_APPROVAL_STATUS", MaintainContractEntities.ApproalStatus);
dp.Add("#D_FROM_DATE", MaintainContractEntities.FromDate);
dp.Add("#D_TO_DATE", MaintainContractEntities.ToDate);
this._db.Query(Constant.SP_GRADE_WISE_SLAB, dp, commandTimeout: 0, commandType: CommandType.StoredProcedure);
}
How can I write test cases which shall cover all the layers i.e from controller to contract but no actual DB to touch?
I am not using Entity Framework, I am using Dapper library.
if you were using EntityFramework, EF now has a InMemoryDatabase.
But that does not seem to be the case.
I have to rewrite some of your "terms" since you are not showing alot of code and the terms are a little confusing.
Controller (WebApiLayer)=> Manager classes (BusinessLogic Layer) => DataLayer (this is where the calls to stored procedures actually exist). From your description, I would say my "DataLayer" is your "Contract" layer......imho, "Contract" is an confusing and ambiguous name....and not a great name for a datalayer. But I digress.
With the above design, you would INJECT some IDataLayer object (for example, IEmployeeDataLayer) interface into your Manager (EmployeeManager : IEmployeeManager). You would have a "real" concrete EmployeeTheRealOneDataLayer object ... and you would also be able to mock IEmployeeDomainDataLayer .. in order to unit test your EmployeeManager object.
I actually have a "close" sample here:
https://github.com/granadacoder/dotnet-core-on-linux-one/blob/master/src/Bal/Managers/EmployeeManager.cs
public class EmployeeManager : IEmployeeManager
{
private readonly ILogger<EmployeeManager> logger;
private readonly IEmployeeDataLayer iedl;
public EmployeeManager(ILoggerFactory loggerFactory, IEmployeeDataLayer iedl)
{
this.logger = loggerFactory.CreateLogger<EmployeeManager>();
this.iedl = iedl;
}
With my unit test code, I would Mock IEmployeeDataLayer , to be able to test the EmployeeManager class.
You question is..how do I test the "real" EmployeeDataLayer without hitting a real database.
This is the i-dont-think-it-exists breaking point. All of that code in the datalayer is coded to (really really) hit a database.
So this is where holy wars start. Some will say "wire it to a sqlexpress database"......but that IMHO, is when these stop becoming unit tests (not running only in memory)..but become more functional tests.
Since you are not using EF, you probably have to make a decision. Be "ok" with writing unit-tests against your business logic layer...and "skip" the DataLayer. In fact, I will put the below attribute on my data-layer classes.
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.excludefromcodecoverageattribute?view=netcore-3.1
Your other choice is to move to something that is more like this : (EF in memory)
https://learn.microsoft.com/en-us/ef/core/providers/in-memory/?tabs=dotnet-core-cli
Personally, (and I actually do this when not using EF) (and I also use Dapper because Dapper performs well).......I skip UNIT testing the datalayer. (Emphasis on the "unit" testing)
But our QA will write FUNCTIONAL tests against a real database engine (think SqlSExpress). The caveat here is that they have to be able to (we pick once a week) completely DELETE/FLUSH the "qa database"....and rebuild it from seed data. This prevents people writing functional tests...looking for hard coded surrogate-(primary-keys) on the tables....but forces looking for items by unique-constraints instead. Aka, it prevents getting "too married" to a specific data inside the qa functional testing database).
(Note, this is a similar concept with the EF In Memory Database...because when you start unit tests with an EF In Memory db, it essentially "is empty" at startup).
PS
You can see a more EF oriented project setup here:
https://github.com/granadacoder/oracle-ef-issues-demo/tree/master/src
PPS
I'm not saying the ideas above are an exhaustive list of possibilities. But when other ideas start crossing the line of "just being in memory"....that's when these mini holy wars start. I am very firm in our company about the "in memory" line in the sand. We used to have alot of "MyProject.Tests.csproj", and this could refer to unit-tests or functional-tests. Now I "strongly encourage" the projects be called "MyProject.UnitTests.csproj" OR "MyProject.FunctionalTests.csproj" to disambiguate. Not everybody loves my "draw line in the sand" approach.

How to mock with LLBLGen

How can you mock LLBLGen? I see that there is an ILinqMetaData interface but it doesn't provide any useful methods to mock out. I'm assuming you would want to program to the ILinqMetaData interface as well as the generated entity interfaces to keep objects loosely coupled to the data. Does anyone have any examples of simple tests/mocks?
I think it's not limited to LLBLGen, maybe this can help:
What's the best strategy for unit-testing database-driven applications?
Personally, I don't normally test my database access or repositories, just the logic that operates on the entities, or integration tests that operate on the entire stack (including the DB).
UPDATE: does this help? it allows you test your logic by mocking the IOrderRepository without having to do any fetch/persistence logic:
public class MyBusinessLogic
{
IOrderRepository orders;
public MyBusinessLogic(IOrderRepository orders)
{
this.orders = orders;
}
public DoSomethingTestable(OrderEntity order)
{
order.Total = 100;
orders.Save(order);
}
}

Unit Testing DbContext

I've researched some information about techniques I could use to unit test a DbContext. I would like to add some in-memory data to the context so that my tests could run against it. I'm using Database-First approach.
The two articles I've found most usefull were this and this.
That approach relies on creating an IContext interface that both MyContext and FakeContext will implement, allowing to Mock the context.
However, I'm trying to avoid using repositories to abstract EF, as pointed by some people, since EF 4.1 already implements repository and unit of work patterns through DbSet and DbContext, and I really would like to preserve all the features implemented by the EF Team without having to maintain them myself with a generic repository, as I already did in other project (and it was kind of painful).
Working with an IContext will lead me to the same path (or won't it?).
I thought about creating a FakeContext that inherits from main MyContext and thus take advantage of the DbContext underneath it to run my tests without hitting the database.
I couldn't find similar implementations, so I'm hoping someone can help me on this.
Am I doing something wrong, or could this lead me to some problems that I'm not anticipating?
Ask yourself a single question: What are you going to test?
You mentioned FakeContext and Mocking the context - why to use both? Those are just different ways to do the same - provide test only implementation of the context.
There is one more bigger problem - faking or mocking context or set has only one result: You are not testing your real code any more.
Simple example:
public interface IContext : IDisposable
{
IDbSet<MyEntity> MyEntities { get; }
}
public class MyEntity
{
public int Id { get; set; }
public string Path { get; set; }
}
public class MyService
{
private bool MyVerySpecialNetMethod(e)
{
return File.Exists(e.Path);
}
public IEnumerable<MyEntity> GetMyEntities()
{
using (IContext context = CreateContext())
{
return context.MyEntities
.Where(e => MyVerySpecialNetMethod(e))
.Select(e)
.ToList();
}
}
}
Now imagine that you have this in your SUT (system under test - in case of unit test it is an unit = usually a method). In the test code you provide FakeContext and FakeSet and it will work - you will have a green test. Now in the production code you will provide a another derived DbContext and DbSet and you will get exception at runtime.
Why? Because by using FakeContext you have also changed LINQ provider and instead of LINQ to Entities you are running LINQ to Objects so calling local .NET methods which cannot be converted to SQL works as well as many other LINQ features which are not available in LINQ to Entities! There are other issues you can find with data modification as well - referential integrity, cascade deletes, etc. That is the reason why I believe that code dealing with context / LINQ to Entities should be covered with integration tests and executed against the real database.
I am developing an open-source library to solve this problem.
http://effort.codeplex.com
A little teaser:
You don't have to add any boilerplate code, just simply call the appropriate API of the library, for example:
var context = Effort.ObjectContextFactory.CreateTransient<MyContext>();
At first this might seem to be magic, but the created ObjectContext object will communicate with an in-memory database and will not talk to the original real database at all. The term "transient" refers to the lifecycle of this database, it only lives during the presence of the created ObjectContext object. Concurrently created ObjectContext objects communicate with dedicated database instances, the data is not shared accross them. This enables to write automated tests easily.
The library provides various features to customize the creation: share data across instances, set initial data of the database, create fake database on different data layers... check out the project site for more info.
As of EF 4.3, you can unit test your code by injecting a fake DefaultConnectionFactory before creating the context.
Entity Framework 4.1 is close to being able to be mocked up in tests but requires a little extra effort. The T4 template provides you with a DbContext derived class that contains DbSet properties. The two things that I think you need to mock are the DbSet objects that these properties return and properites and methods you're using on the DbContext derived class. Both can be achieved by modifying the T4 template.
Brent McKendrick has shown the types of modifications that need to be made in this post, but not the T4 template modifications that can achieve this. Roughly, these are:
Convert the DbSet properties on the DbContext derived class into IDbSet properties.
Add a section that generates an interface for the DbContext derived class containing the IDbSet properties and any other methods (such as SaveChanges) that you'll need to mock.
Implement the new interface in the DbContext derived class.

Can I unit test a method that makes Sitecore context calls?

I'm working on a web application that is built over Sitecore CMS. I was wondering if we could unit test for example a method that takes some data from Sitecore makes some processing with it and spits out a result. I would like to test all the logic within the method via a unit test.
I pretty confused after searching the internet wide and deep. Some say that this kind of testing is actually integration testing and not unit testing and I should test only the code that has no Sitecore calls, others say that this is not possible because the Sitecore context would be missing.
I would like to ask for your help experienced fellow programmers:
Can I unit test a method that contains Sitecore calls ? If YES, how ? If NO, why ? Is there any workaround ?
The project is at its beginning, so there will be no problem in choosing between unit testing frameworks such as MSTest or Nunit, if it is the case that the solution is related to the unit testing framework of choice.
It's pretty hard to find out anything about Sitecore without providing email and living through the sales pitch, so I'll just provide a generic approach on how to do something like this.
First and foremost, you assume that the Sitecore API is guaranteed to work - i.e. it's a framework - and you don't unit test it. You should be unit testing your interactions with it.
Then, download MOQ and read the quick start on how to use it. This is my preferred mocking framework. Feel free to use other frameworks if you wish.
Hopefully, Sitecore API provides a way for you to create data objects without dealing with persistence - i.e. to simply create a new instance of whatever it is you are interested in. Here is my imaginary API:
public class Post {
public string Body {get;set;}
public DateTime LastModified {get;set;}
public string Title {get;set;}
}
public interface ISiteCorePosts {
public IEnumerable<Post> GetPostsByUser(int userId);
}
In this case unit testing should be fairly easy. With a bit of Dependency Injection, you can inject the SiteCore interfaces into your component and then unit test it.
public class MyPostProcessor {
private readonly ISiteCorePosts m_postRepository;
public MyPostProcessor(ISiteCorePosts postRepository) {
m_postRepository = postRepository;
}
public void ProcessPosts(int userId) {
var posts = m_postRepository.GetPostsByUser(userId);
//do something with posts
}
}
public class MyPostProcessorTest {
[TestMethod]
ProcessPostsShouldCallGetPostsByUser() {
var siteCorePostsMock = new Mock<ISiteCorePosts>();
//Sets up the mock to return a list of posts when called with userId = 5
siteCorePostsMock.Setup(m=>m.GetPostsByUser(5)).Returns(new List<Post>{/*fake posts*/});
MyPostProcessor target = new MyPostProcessor(siteCorePostsMock.Object);
target.ProcessPosts(5);
//Verifies that all setups are called
siteCorePostsMock.VerifyAll();
}
}
If ISiteCorePosts is not, in fact, an interface and is a concrete class whose methods are not virtual and thus cannot be mocked, you will need to use Facade pattern to wrap the SiteCore interaction to make it more testing friendly.
public class SiteCorePostsFacade {
SiteCorePosts m_Posts = new SiteCorePosts();
//important - make this method virtual so it can be mocked without needing an interface
public virtual IEnumerable<Post> GetPostsByUser(int userId) {
return m_Posts.GetPostsByUser(userId);
}
}
You then proceed to use SiteCorePostsFacade as though it was an interface in the previous example. Good thing about MOQ is that it allows you to mock concrete classes with virtual methods, not just interfaces.
With this approach, you should be able to inject all sorts of data into your application to test all interactions with SiteCore API.
we have used a custom WebControl placed on a WebForm for our integration tests some years now, which wraps the NUnit Test Suite runner functionality much like the NUnit GUI. It show a pretty grid of executed tests with links to fixtures and categories to execute specific tests. Its created much like described here http://adeneys.wordpress.com/2010/04/13/new-technique-for-unit-testing-renderings-in-sitecore/ (the custom test runner part). Our implementation can also return raw NUnit xml for further processing by for example a build server.
I've tried MSTest a while back and it also works when specified that it should launch a WebDev / IIS site to test. It works but is extremely slow compared to above solution.
Happy testing!
Short answer:
You need to mock calls to SiteCore CMS.
Long answer:
I am not aware about SiteCore CMS. But, from your question looks like it is something that is external to your application. Components external to your system should always be used via interface. This has two benefits:
If you want to use another CMS system, you can easily do as your application is just talking to an interface.
It helps you with behavior testing by mocking the interface.
The code you write is your responsibility and hence you should only unit test that piece of code. Your unit tests should ensure that your code calls appropriate SiteCode CMS methods in various scenarios (behavior tests). You can do this using mocking. I use moq for mocking.
As tugga said, it depends upon how tightly the code you want to test is coupled to SiteCore. If it's something like:
SomeSiteCoreService siteCoreDependency = new SomeSiteCoreService()
Then this would be very difficult to test. If SiteCore provides you an interface, then you have more flexibility to unit test it. You could pass the implementation into your method either (contstructor, class property, or method parameter) and then you can send in a fake implementation of that service.
If they do not provide you with an interface, then you have to do a little more work. You would write an adapter interface of your own and the default implementation would delegate to the 3rd party dependency.
public interface ICMSAdapter{
void DoSomethingWithCMS()
}
public class SiteCoreCMSAdapter: ICMSAdapter{
SiteCoreService _cms = new SiteCoreService();
public void DoSomethingWithCMS(){
_cms.DoSomething();
}
That keeps your 3rd party dependencies at arms length and provides seams to all sorts of cool things, like unit tests and you do interception style architecture and do your own thing before and after the call.
}
I was able to get unit tests to interact with sitecore api in VS 2015. The same test throws a StackOverflow exception when run in VS 2012.
For example, this method call runs fine in VS2015 but not VS2015:
Context.SetActiveSite("mysite");
quick note: this assumes you have a site named mysite setup in your config file

How to mock ObjectContext or ObjectQuery<T> in Entity Framework?

How to mock ObjectContext or ObjectQuery in Entity Framework?
The basic mocking frameworks can only create mocks for interfaces and for abstract classes (but only for abstract/virtual methods).
As the ObjectContext is neither abstract nor interface, it is not so easy to mock it. However, as the concrete model container is generated as partial class (if you use the designer), you can extract the methods/properties you need from it to an interface. In your code, you may use the interface only, that you can mock afterwards.
With the ObjectQuery it is a little bit more easy, as it has a base interface (e.g. IQueryable) that basically contains all the neccessary operations that you usually need (and required for LINQ). So you should expose IQueryable instead of ObjectQuery in your business logic, and you can create mock for that interface.
Other alternative is to hide all data-access related logic into a separate layer (with minimal logic), test this layer with integration tests, and mock it to be able to unit test the other layers.
There are tools (I know only TypeMock) that use the profiling hooks of .NET to generate the mocks. These tools are not limited to mock interfaces or abstract classes, but with them you can mock basically anything, including non-virtual and static methods. With such a tool you don't need to change your business logic in order to allow mocking.
Although this approach is sometimes useful, you have to be aware that extracting the dependencies to interfaces (IoC) is not only helpful for mocking, but also it reduces the dependencies between your components, that has other benefits too.
Personally I like Rhino.Mocks the best from the freeware tools, but we also use TypeMock as well, which is also a great product (but you have to pay for it).
Why can't we just create the actual context object to be used in our tests? Since we don't want our tests to affect the production database, we can always specify a connection string that points to a test database. Before running each test, construct a new context, add the data you will need in your test, proceed with the unit test, then in the test cleanup section, delete all the records that were created during the test. The only side-affect here would be that the auto-increment IDs would be used up in the test database, but since it's a test database - who cares?
I know that most answers regarding this question propose using DI/IoC designs to create interfaces for data contexts etc. but the reason I am using Entity Framework is exactly to not write any interfaces for my database connections, object models, and simple CRUD transactions. To write mock interfaces for my data objects and to write complex queryable objects to support LINQ, defeats the purpose of relying on highly-tested and reliable Entity Framework.
This pattern for unit testing is not new - Ruby on Rails has been using it for a long time and it's worked out great. Just as .NET provides EF, RoR provides ActiveRecord objects and each unit test creates the objects it needs, proceeds with the tests, and then deletes all the constructed records.
How to specify connection string for test environment? Since all tests are in their own dedicated test project, adding a new App.Config file with a connection string for the test database would suffice.
Just think of how much headache and pain this will save you.
I agree with the others you cannot really Mock ObjectContext. You should use EF DbContext because you can mock the underlying DbSet There are quite a lot of post how to do that. So I won't write how to do it. However if you absolutely must use ObjectContext (for some reason) and you want to Unit test it you can use InMemory database.
First install this Nuget package: Effort (Entity Framework Fake ObjectContext Realization Tool), which uses NMemory as the database. Install Effort.EF6 package:
PM> Install-Package Effort.EF6
using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using Effort;
public class DbContextHelper
{
//Fake object you can drop this if you are using your own EF context
private class DbObject
{
public Guid Id { get; set; }
public string Name { get; set; }
}
//Fake EF context you can switch with you own EF context
private class FakeDbContext : DbContext
{
public FakeDbContext(DbConnection connection)
: base(connection, true) { }
public virtual DbSet<DbObject> DbObjects { get; set; }
}
private FakeDbContext _dbContext;
public DbContextHelper()
{
//In memory DB connection
DbConnection effortConnection = DbConnectionFactory.CreatePersistent("TestInstanceName");
_dbContext = new FakeDbContext(effortConnection);
}
//You can expose your context instead of the DbContext base type
public DbContext DbContext => _dbContext;
public ObjectContext ObjectContext => ((IObjectContextAdapter)_dbContext).ObjectContext;
//Method to add Fake object to the fake EF context
public void AddEntityWithState(string value, EntityState entityState)
{
DbContext.Entry(new DbObject() { Id = Guid.NewGuid(), Name = value }).State = entityState;
}
}
Usage:
DbContextHelper _dbContextHelper = new DbContextHelper();
_dbContextHelper.AddEntityWithState("added", System.Data.Entity.EntityState.Added);
_dbContextHelper.AddEntityWithState("added", System.Data.Entity.EntityState.Modified);
var objs = _dbContextHelper.ObjectContext.GetObjectStateEntries(EntityState.Modified | EntityState.Added);
There you are you have your object in memory DB.