This is a migrated thread and some comments may be shown as answers.

Mock EF6 DBContext

2 Answers 152 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Josh
Top achievements
Rank 1
Josh asked on 04 Oct 2015, 06:56 PM

Downloaded the trial of JustMock since so many of the problems I have been facing are supposed to be addressable with it. I'm attempting to Mock an EF 6.1.3 DBContext. I have can build a test that runs directly against the DB and it works fine, but when I run against the Mocked Context I get an exception.

 To be clear I am using JustMock version 2015.3.929.5 also per the documentation I downloaded JustMock.EntityFramework from Nuget version 1.0.1. The Nuget installed incorrectly into the project and tried to explicitly target JustMock 2014.1.1424.1, but I corrected the config file back to the currently referenced version as mentioned above.

Here is my code.

public class Account
{
 public int Id { get; set; }
 [Required]
 public string ExternalId { get; set; }
 public string AccountTimeZone { get; set; }
 public string FipsCode { get; set; }
 public bool DVREnabled { get; set; }
 public bool Enabled { get; set; }
 public double CreditLimit { get; set; }
 public int SdStreams { get; set; }
 public int HdStreams { get; set; }
 [Column(TypeName="DateTime2")]
 public DateTime CreatedTimeUTC { get; set; }
 [Column(TypeName = "DateTime2")]
 public DateTime LastUpdateTimeUTC { get; set; }
 public string CreatedBy { get; set; }
 public string UpdatedBy { get; set; }
 public AccountStatus AccountStatus { get; set; }
 public List<Device> Devices { get; set; }
 public List<SubscriberGroup> SubscriberGroups { get; set; }
 public List<AccountValue> AccountValues { get; set; }
 public SubscriberInfo SubscriberInfo { get; set; }
 public Device RecordingDevice { get; set; }
 [Required]
 public Tenant Tenant { get; set; }
 public List<Phone> Phones { get; set; }
 public List<AccountHistory> AccountHistory { get; set; }
}

 

 

public class Tenant
{
 public int Id { get; set; }
 public string TenantName { get; set; }
 public string TenantDescription { get; set; }
 public string MediaroomVersion { get; set; }
 public TenantConfiguration TenantConfiguration { get; set; }
 public List<Account> Accounts { get; set; }
 public List<Device> Devices { get; set; }
 public List<ChangeEvent> ChangeEvents { get; set; }
}

 

public class EmptyAccount
{
    public void CreateEmptyAccountInConductor(Account newAccount, int tenantId, string requestedBy, UnitOfWork uow)
    {
    var tr = new TenantRepository(uow);
    var tenant = tr.Find(tenantId);
    tenant.Accounts.Add(new Account(){ExternalId = newAccount.ExternalId, CreatedBy = requestedBy});
 
    tr.InsertOrUpdate(tenant);
    uow.Save();           
    }
}

 

public class TenantRepository : ITenantRepository
{
    private readonly ConductorContext _context;
 
    public TenantRepository(UnitOfWork uow)
    {
        _context = uow.Context;
    }
 
    public Tenant Find(int id)
    {
        return _context.Tenants.Find(id);
    }
 
    public void InsertOrUpdate(Tenant entity)
    {
        if (entity.Id == default(int))
        {
            _context.Entry(entity).State = EntityState.Added;
        }
        else
        {
        _context.Entry(entity).State = EntityState.Modified;
        }
    }
}

 

public class ConductorContext : DbContext
{
    public ConductorContext()
    {
        base.Configuration.ProxyCreationEnabled = false;
    }
 
    public DbSet<Account> Accounts { get; set; }
    public DbSet<AccountHistory> AccountHistories { get; set; }
    public DbSet<AccountTemplate> AccountTemplates { get; set; }
    public DbSet<AccountValue> AccountValues { get; set; }
    public DbSet<ChangeEvent> ChangeEvents { get; set; }
    public DbSet<Device> Devices { get; set; }
    public DbSet<DeviceValue> DeviceValues { get; set; }
    public DbSet<Phone> Phones { get; set; }
    public DbSet<SubscriberGroup> SubscriberGroups { get; set; }
    public DbSet<SubscriberInfo> SubscribersInfo { get; set; }
    public DbSet<Tenant> Tenants { get; set; }
    public DbSet<TenantConfiguration> TenantConfigurations { get; set; }
}

  

public class UnitOfWork : IUnitOfWork<ConductorContext>
{
    private readonly ConductorContext _context;
 
    public UnitOfWork()
    {
        _context = new ConductorContext();
    }
 
    public UnitOfWork(ConductorContext context)
    {
        _context = context;
    }
 
 
    public int Save()
    {
        return _context.SaveChanges();
    }
 
 
    public void Dispose()
    {
        _context.Dispose();
    }
 
    public ConductorContext Context
    {
        get { return _context; }
    }
}

 

 Direct to DB test that works.

[Test]
public void CreateEmptyAccountInConductor4()
{
    // Arrange
    Database.SetInitializer(new DropCreateDatabaseAlways<ConductorContext>());
    var ctx = new ConductorContext();
    var fixture = new Fixture();
 
    var account = fixture.Build<Account>()
    .Without(p => p.Id)
    .Without(p => p.Tenant)
    .Without(p => p.AccountHistory)
    .Without(p => p.AccountValues)
    .Without(p => p.Devices)
    .Without(p => p.Phones)
    .Without(p => p.SubscriberGroups)
    .Without(p => p.SubscriberInfo)
    .Without(p => p.RecordingDevice)
    .Without(p => p.CreatedTimeUTC)
    .Without(p => p.LastUpdateTimeUTC)
    .Create();
 
    var tenant = fixture.Build<Tenant>()
    .With(p => p.Id, 1)
    .With(p => p.MediaroomVersion, "V2")
    .Without(p => p.Accounts)
    .Without(p => p.Devices)
    .Without(p => p.ChangeEvents)
    .With(p => p.TenantConfiguration, new TenantConfiguration())
    .Create();
 
    ctx.Tenants.Add(tenant);
    ctx.SaveChanges(); 
 
    // Act
    var sut = new EmptyAccount();
 
    sut.CreateEmptyAccountInConductor(account, 1, fixture.Create<string>(), new UnitOfWork(ctx));
 
    ctx.Dispose();
 
    // Assert
    ctx = new ConductorContext();
    // Force entity to load into context.
    var tenantAfter = ctx.Tenants.Find(1);
    var accountAfter = ctx.Accounts.Find(1);
    Assert.AreEqual(account.ExternalId, ctx.Tenants.Find(1).Accounts.Single(p => p.ExternalId == account.ExternalId).ExternalId);
}

 

Mocked Context that fails with a NullReferanceException in the InsertOrUpdate method of TenantRepository.

[Test]
public void CreateEmptyAccountInConductor3()
{
    // Arrange
    var ctx = Mock.Create<ConductorContext>().PrepareMock();
 
    var fixture = new Fixture();
 
    var account = fixture.Build<Account>()
    .Without(p => p.Id)
    .Without(p => p.Tenant)
    .Without(p => p.AccountHistory)
    .Without(p => p.AccountValues)
    .Without(p => p.Devices)
    .Without(p => p.Phones)
    .Without(p => p.SubscriberGroups)
    .Without(p => p.SubscriberInfo)
    .Without(p => p.RecordingDevice)
    .Without(p => p.CreatedTimeUTC)
    .Without(p => p.LastUpdateTimeUTC)
    .Create();
 
    var tenant = fixture.Build<Tenant>()
    .With(p => p.Id, 1)
    .With(p => p.MediaroomVersion, "V2")
    .With(p => p.Accounts, new List<Account>())
    .Without(p => p.Devices)
    .Without(p => p.ChangeEvents)
    .With(p => p.TenantConfiguration, new TenantConfiguration())
    .Create();
 
    var tenantList = new List<Tenant>()
    {
    tenant
    };
 
    ctx.Tenants.Bind(tenantList);
 
    // Act
    var sut = new EmptyAccount();
    sut.CreateEmptyAccountInConductor(account, 1, fixture.Create<string>(), new UnitOfWork(ctx));
 
    // Assert
    Mock.Assert(() => ctx.SaveChanges(), Occurs.Once());
}

 

My assertion test for the Mocked Context is never even reached in the failing test. At this point I assume I'm doing something wrong. Any idea how I can get this to work because I don't want to be creating dropping my database over and over to run my test. This is just one of many I need to write like this.

 

 

 

2 Answers, 1 is accepted

Sort by
0
Accepted
Stefan
Telerik team
answered on 06 Oct 2015, 09:20 AM
Hello Josh,

As I mentioned in your support ticket, your test is fine. The issue lies with the Resharper test runner, which, for some reason, decides not to let the JustMock profiler run.

Regards,
Stefan
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Josh
Top achievements
Rank 1
answered on 07 Oct 2015, 02:59 AM

Appears to be user error on my part. For some reason during my testing of different scenarios I had disabled the profiler and forgot that it was off. Re-enabling it fixed the problem.

 

Thanks.

Tags
General Discussions
Asked by
Josh
Top achievements
Rank 1
Answers by
Stefan
Telerik team
Josh
Top achievements
Rank 1
Share this question
or