Reputation: 21136
I made a change to an entity, ran a migration and updated the database. I then re-ran a test and it's throwing an error:
The model backing the 'EFDbContextProxy' context has changed since the database was created. Consider using Code First Migrations to update the database
If I run the application, I do not get this error. It seems my EFDbContextProxy (Whatever the hell that is) is using an old cache of the data structure.
Any ideas how to resolve this?
This is how I prepare my db context in my test:
public class EFFieldViewerRepository_Setup
{
protected DateTime now;
protected Mock<EFDbContext> mockDbContext;
protected EFFieldViewerRepository fieldViewerRepository;
protected IDbSet<FieldViewer> fieldViewerDbSet;
public EFFieldViewerRepository_Setup()
{
this.now = DateTime.Now;
this.mockDbContext = new Mock<EFDbContext>() { CallBase = true };
this.fieldViewerRepository = new EFFieldViewerRepository( this.mockDbContext.Object );
...
}
Here is my stack trace: http://pastebin.com/kAUmhi3j
Upvotes: 1
Views: 393
Reputation: 601
If Entity Framework is configured to produce a LocalDB database, Moq's DBContext proxy class created by Castle will, in turn, create a LocalDB database which may be out of sync with EF Migrations added after the database is initially created. I found that deleting the LocalDB database would solve the problem, though there are probably better solutions including the answer provided @Jimmyt1988.
I was running unit tests with Moq in a Visual Studio test project which also had integration tests that connected to the target database. Because of this, I had ended up having a node in my app.config like this.
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
My Moq test setup is similar to the @Jimmyt1988's
private Mock<DbSet<OutgoingEntry>> _set;
private Mock<MyContext> _context;
private ModelService<OutgoingEntry, MyContext> _service;
[NUnit.Framework.SetUp]
public void Setup()
{
_set = new Mock<DbSet<OutgoingEntry>>();
_set.Reset();
_context = new Mock<MyContext>();
_context.Reset();
_context.Setup(m => m.OutgoingEntries).Returns(_set.Object);
_context.Setup(m => m.Set<OutgoingEntry>()).Returns(_set.Object);
_service = new OutgoingService(_context.Object);
}
In the example above, _context.Object
is an instance of Castle.Proxies.MyContextProxy
. This is generated at runtime to allow Moq to override Methods and Properties. However, if EF is configured as above, generation of the proxy class will still trigger database initialization. This ultimately results in a database like this:
All the details above were more or less transparent to me when I added a new migration. This, unfortunately, resulted in the exact error mentioned in the original question. To resolve the underlying issue, I simply deleted the LocalDB file created by Moq/Castle. It's trickier than it sounds. I found these specific steps worked on Windows 10.
SqlLocalDB.exe stop mssqllocaldb
.SqlLocalDB.exe delete mssqllocaldb
This command will effectively delete any LocalDB databases you have. Only do this if you don't care about your LocalDB mssqllocaldb instance.Upvotes: 1
Reputation: 21136
I had to create a MockEFDbContext and extend off of EFDbContext. Inside the construct I run the Database.SetInitializer<EFDbContext>(null)
:
public class MockEFDbContext : EFDbContext
{
public MockEFDbContext()
{
Database.SetInitializer<EFDbContext>(null);
}
}
I then used this new MockEFDbContext
in my tests rather than the normal one:
this.mockDbContext = new Mock<MockEFDbContext>() { CallBase = true };
Sources:
- http://gaui.is/how-to-mock-the-datacontext-entity-framework/
- https://msdn.microsoft.com/en-us/library/gg679461(v=vs.113).aspx
Upvotes: 1