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.