For testing purposes, I want to create a mock of the autogenerated EF context class (DB first). In order to do that, I've generated a matching interface and made the autogenerated class implement this interface (simply by adding the interface to the T4 template). So now my EF context looks like this: class MyContext : DbContext, IContext
IContext has all the properties that MyContext and DbContext has. The next stage is to create a mock class that implements the same interface. So now I also have: class MyContextMock : IContext
.
Now for the problematic part: A part of my code uses a property of DbContext named Configuration of type DbContextConfiguration (This property allows me to turn off the "auto detect changes" feature). The issue is that now I need to create an instance of DbContextConfiguration for my mock, but DbContextConfiguration has only internal constructors and it doesn't implement any interfaces. This means I can't directly create an instance of it, and I can't inherit it (thanks Microsoft).
I've successfully managed to create an instance of DbContextConfiguration using reflection, but unfortunately it is unusable. I can give more details about this attempt, but it's like going down a deep rabbit hole of internal objects instantiations and I can't see how this approach will work.
So is Entity Framework truely unmockable or is there something I can do?
In your specific case it seems like a better option to have a method/property added to your IContext, that toggles AutoDetectChanges feature:
public interface IContext {
//....
bool AutoDetectChanges { get; set; }
bool LazyLoadingEnabled { get; set; }
//etc..
}
You can probably even wrap it around to some configuration class:
public interface IContext {
//....
IContextOrmOptions Options { get; set; }
}
public interface IContextOrmOptions {
bool AutoDetectChanges { get; set; }
bool LazyLoadingEnabled { get; set; }
//etc..
}
//real implementation
public class EntityFrameworkContextOrmOptions : IContextOrmOptions {
private DbContext _dbContext;
public EntityFrameworkContextOrmOptions(DbContext dbContext) {
dbContext = _dbContext;
}
public bool AutoDetectChanges {
{ get { return _dbContext.Configuration.AutoDetectChangesEnabled; } }
{ set { _dbContext.Configuration.AutoDetectChangesEnabled = value; } }
}
}
Unfortunately, this approach kinda breaks ORM-agnosticness of your system, maybe there's a way for you to avoid this kind of code?
This will also make you have problems if you will want to mock .Entry()
method, since it provides a whole lot of methods for you -- but this can be hard anyways.
It's far more simple than what you are trying to do and of course the DbContext can be mocked. This is a good article/tutorial to start with:
https://msdn.microsoft.com/en-us/library/dn314429.aspx
Assuming you are on EF 6+
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.