public void WhenUsingSharedDatabaseAndMigrator_ShouldOnlyMigrateTheFirstTime() { using (var db = new TempDBLocalDb()) { var sql = ENTITY_PERSISTENCE_CONTEXT_SQL; EntityPersistenceTester.CreateFor <SomeEntityWithDecimalValue>() .WithContext <EntityPersistenceContext>() .WithDbMigrator(cs => new DbSchemaImporter(cs, sql)) .WithSharedDatabase(db) .ShouldPersistAndRecall(); // need to clear for the test to work again using (var ctx = new EntityPersistenceContext(db.CreateConnection())) { ctx.EntitiesWithDecimalValues.Clear(); ctx.SaveChangesWithErrorReporting(); } Assert.DoesNotThrow(() => { EntityPersistenceTester.CreateFor <SomeEntityWithDecimalValue>() .WithContext <EntityPersistenceContext>() .WithDbMigrator(cs => new DbSchemaImporter(cs, sql)) .WithSharedDatabase(db) .ShouldPersistAndRecall(); }); } }
public void Tester_ShouldBeAbleToShareATempDb() { //---------------Set up test pack------------------- var tempDb = new TempDbWithCallInformation(); using (new AutoResetter(() => { }, () => tempDb.Dispose())) { //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithSharedDatabase(tempDb) .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .ShouldPersistAndRecall(); Assert.AreEqual(0, tempDb.DisposeCalls); using (var ctx = new CommunicatorContext(tempDb.CreateConnection())) { ctx.BlockListReasons.Clear(); // required to allow the persistence test to complete ctx.SaveChangesWithErrorReporting(); } EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithSharedDatabase(tempDb) .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.AreEqual(0, tempDb.DisposeCalls); } }
public void Tester_WithoutAfterPersisting_ShouldWorkTheSame() { //---------------Set up test pack------------------- var beforePersistingCalled = false; //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithCollection(ctx => ctx.BlockListReasons) .WithBuilder <ComBlockListReasonBuilder>() .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .BeforePersisting((ctx, entity) => { beforePersistingCalled = true; Assert.IsNotNull(ctx); Assert.IsInstanceOf <CommunicatorContext>(ctx); Assert.IsNotNull(entity); Assert.IsInstanceOf <COMBlockListReason>(entity); }) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.IsTrue(beforePersistingCalled); }
public void Tester_WithoutBeforePersisting_ShouldWorkTheSame() { //---------------Set up test pack------------------- var afterPersistingCalled = false; //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithBuilder <ComBlockListReasonBuilder>() .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .AfterPersisting((before, after) => { afterPersistingCalled = true; Assert.IsNotNull(before); Assert.IsNotNull(after); Assert.AreNotEqual(before, after); before.GetType().ShouldBeAssignableFrom <COMBlockListReason>(); }) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.IsTrue(afterPersistingCalled); }
public void EmailAttachment_ShouldBeAbleToPersistAndRecall() { EntityPersistenceTester.CreateFor <EmailAttachment>() .WithContext <EmailContext>() .WithDbMigrator(MigratorFactory) .WithSharedDatabase(_sharedTempDb) .WithAllowedDateTimePropertyDelta(_oneSecond) .ShouldPersistAndRecall(); }
public void WithAllowedDateTimeDelta_GivenDelta_WhenDeltaIsExceeded_ShouldThrow() { // Pre-amble: I've noticed that, periodically, a test against an entity // with a DateTime field will fail: the persisted entity will come back // with the field different by one (rarely two) milliseconds. Mostly, // in production, timestamps are only used to seconds precision, so mostly, // we don't actually care. The point of this test is to fail on the few that do // when we're not catering for the delta. The plan is: // 1) add a WithAllowedDateTimeDelta method which takes a timespan // - so the consumer can specify exactly how fine to make the // allowance // 2) default to using an allowed delta which covers the observed test flops (so // probably 2 ms) //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- var exceptions = new List <Exception>(); using (new TestExecutionContext.IsolatedContext()) { var attempts = 0; while (attempts++ < 10) { Parallel.For( 0, 4, (i, state) => { // at least one of these should hit the issue try { EntityPersistenceTester.CreateFor <SomeEntityWithDateTimeValue>() .WithContext <ContextForDateTimeDeltaTesting>() .WithAllowedDateTimePropertyDelta( new TimeSpan(0, 0, 0, 0, 1)) // there should be at least one 2ms delta .SuppressMissingMigratorMessage() .ShouldPersistAndRecall(); } catch (Exception ex) { state.Stop(); exceptions.Add(ex); } }); if (exceptions.Any()) { break; } } } //---------------Test Result ----------------------- CollectionAssert.IsNotEmpty(exceptions); }
public void CreateFor_ShouldReturnEntityPersistenceTester() { //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- var result = EntityPersistenceTester.CreateFor <COMBlockListReason>(); //---------------Test Result ----------------------- Assert.IsNotNull(result); Assert.IsInstanceOf <EntityPersistenceTesterFor <COMBlockListReason> >(result); }
public void ActingOnEntitiesWithTracking() { //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <SomeEntityWithDecimalValue>() .WithContext <EntityPersistenceContext>() .WithDbMigrator(s => new DbSchemaImporter(s, TestResources.entitypersistence)) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- }
public void ShortestPossibleUsefulUsage_CoversSimplestCases() { //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockList>() .WithContext <CommunicatorContext>() .WithDbMigrator(s => new DbSchemaImporter(s, TestResources.dbscript)) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- }
public void LoanItem_ShouldBeAbleToPersistAndRecall() { //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- using (var ctx = new WimsDbContext(_tempDb.CreateConnection())) Clear(ctx); EntityPersistenceTester.CreateFor <LoanItem>() .WithContext <WimsDbContext>() .WithSharedDatabase(_tempDb) .WithEntityFrameworkLogger(Console.WriteLine) .WithDbMigrator(conn => new MigrationsRunner(conn)) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- }
public void SomeChildEntity_ShouldBeAbleToPersistAndRecall() { // this is a more fluent approach to the same test above //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- // option 1: spin up a clean db every time and migrate EntityPersistenceTester.CreateFor <SomeChildEntity>() .WithContext <SomeContext>() // totally optional: the test helper will search for an existing builder or // create one on the fly (which would be re-used the next time someone needs one) .WithBuilder <SomeChildEntityBuilder>() .WithDbMigrator(connectionString => new CompositeDBMigrator(connectionString, true)) // optional: the tester can figure this out .WithCollection(ctx => ctx.SomeChildEntities) .BeforePersisting((ctx, entity) => { Assert.IsNotNull(entity.SomeEntity); }) .AfterPersisting((entityBefore, entityAfter) => { // no assertions done here in this test, but this is where you would // do custom assertions }) // totally optional: the default is for the tester to ignore virtual properties (ie, navigation properties) .WithIgnoredProperties(typeof(SomeChildEntity).VirtualProperties()) // also optional: how much drift to allow for datetime property persistence // the amount which makes sense depends on your backing field's resolution // - the default behaviour allows just enough difference for most sql server implementations .WithAllowedDateTimePropertyDelta(TimeSpan.FromMilliseconds(100)) .ShouldPersistAndRecall(); // option 2: using the shared database from the base context // - which requires: // [OneTimeSetup] should call Configure and perform migrations // [SetUp] should clear out the context to avoid collisions with the tester EntityPersistenceTester.CreateFor <SomeChildEntity>() .WithContext <SomeContext>() .WithSharedDatabase(_tempDb) .BeforePersisting((ctx, entity) => { Assert.IsNotNull(entity.SomeEntity); }) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- }
public void Tester_WithoutAnyUserSetupOrValidation_ShouldWorkTheSame() { //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithCollection(ctx => ctx.BlockListReasons) .WithBuilder <ComBlockListReasonBuilder>() .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- }
public void Tester_ShouldBeAbleToBeGivenAFuncToCreateTheTempDb() { //---------------Set up test pack------------------- var beforePersistingCalled = false; var afterPersistingCalled = false; var tempDb = new TempDbWithCallInformation(); using (new AutoResetter(() => { }, () => tempDb.ActualDispose())) { Assert.AreEqual(0, tempDb.DisposeCalls); //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithTempDbFactory(() => tempDb) .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .BeforePersisting((ctx, entity) => { beforePersistingCalled = true; Assert.IsNotNull(ctx); Assert.IsInstanceOf <CommunicatorContext>(ctx); Assert.IsNotNull(entity); Assert.IsInstanceOf <COMBlockListReason>(entity); }) .AfterPersisting((before, after) => { afterPersistingCalled = true; Assert.IsNotNull(before); Assert.IsNotNull(after); Assert.AreNotEqual(before, after); before.GetType().ShouldBeAssignableFrom <COMBlockListReason>(); }) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.IsTrue(beforePersistingCalled); Assert.IsTrue(afterPersistingCalled); Assert.AreEqual(1, tempDb.DisposeCalls); // test that the provided tempdb was actually used AssertHasTable(tempDb, "COMBlockListReason"); AssertTableIsNotEmpty(tempDb, "COMBlockListReason"); } }
public void SuppressMissingMigratorMessage_ShouldSuppressMissingMigratorMessage() { //---------------Set up test pack------------------- string logMessage = null; //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithLogAction(s => logMessage = s) .SuppressMissingMigratorMessage() .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.IsNull(logMessage); }
public void UsingDefaultDeltaOf2Ms_ShouldAllowTestItemDateTimePropertyValuesToDifferByThatDelta() { // Pre-amble: I've noticed that, periodically, a test against an entity // with a DateTime field will fail: the persisted entity will come back // with the field different by one (rarely two) milliseconds. Mostly, // in production, timestamps are only used to seconds precision, so mostly, // we don't actually care. The point of this test is to fail on the few that do // when we're not catering for the delta. The plan is: // 1) add a WithAllowedDateTimeDelta method which takes a timespan // - so the consumer can specify exactly how fine to make the // allowance // 2) default to using an allowed delta which covers the observed test flops (so // probably 2 ms) //---------------Set up test pack------------------- //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- var exceptions = new List <Exception>(); Parallel.For(0, 5, (i, state) => { // at least one of these should hit the issue try { EntityPersistenceTester.CreateFor <SomeEntityWithDateTimeValue>() .WithContext <ContextForDateTimeDeltaTesting>() .SuppressMissingMigratorMessage() .ShouldPersistAndRecall(); } catch (Exception ex) { state.Stop(); exceptions.Add(ex); } }); //---------------Test Result ----------------------- if (exceptions.Any()) { exceptions.ForEach(e => Console.WriteLine(e.Message)); } CollectionAssert.IsEmpty(exceptions); }
public void WhenNoMigratorAndNoSuppressMissingMigratorMessage_ShouldWarnAboutMigrator() { //---------------Set up test pack------------------- string logMessage = null; //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithLogAction(s => logMessage = s) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.IsNotNull(logMessage); StringAssert.Contains("warning", logMessage.ToLower(CultureInfo.InvariantCulture)); StringAssert.Contains("entityframework will perform migrations", logMessage.ToLower(CultureInfo.InvariantCulture)); StringAssert.Contains("to suppress this message", logMessage.ToLower(CultureInfo.InvariantCulture)); }
public void WithEntityFrameworkLogger_ShouldLogUsingProvidedAction() { //---------------Set up test pack------------------- var logLines = new List <string>(); //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockList>() .WithContext <CommunicatorContext>() .WithEntityFrameworkLogger(logLines.Add) .WithDbMigrator(s => new DbSchemaImporter(s, TestResources.dbscript)) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- CollectionAssert.IsNotEmpty(logLines); var total = string.Join("\n", logLines).ToLower(CultureInfo.InvariantCulture); StringAssert.Contains("insert", total); StringAssert.Contains("select", total); StringAssert.Contains("comblocklist", total); }
public void ShouldCallAllBeforeAndAfterPersistingBlocks_InRegistrationOrder() { //--------------- Arrange ------------------- var allCalls = 0; //--------------- Assume ---------------- //--------------- Act ---------------------- EntityPersistenceTester.CreateFor <SomeEntityWithDecimalValue>() .WithContext <EntityPersistenceContext>() .WithDbMigrator(s => new DbSchemaImporter(s, TestResources.entitypersistence)) .BeforePersisting((ctx, entity) => { entity.DecimalValue = 1; allCalls++; }) .BeforePersisting((ctx, entity) => { Assert.AreEqual(1, entity.DecimalValue); entity.DecimalValue = 2; allCalls++; }) .AfterPersisting((before, after) => { Assert.AreEqual(2, after.DecimalValue); after.DecimalValue = 3; allCalls++; }) .AfterPersisting((before, after) => { Assert.AreEqual(after.DecimalValue, 3); allCalls++; }) .ShouldPersistAndRecall(); //--------------- Assert ----------------------- Assert.AreEqual(4, allCalls); }
public void Tester_WithAllPriorProvidedStuffs_ShouldWorkTheSame() { //---------------Set up test pack------------------- var beforePersistingCalled = false; var afterPersistingCalled = false; //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- EntityPersistenceTester.CreateFor <COMBlockListReason>() .WithContext <CommunicatorContext>() .WithCollection(ctx => ctx.BlockListReasons) .WithBuilder <ComBlockListReasonBuilder>() .WithIgnoredProperties("COMBlockListReasonID") // not actually required .WithDbMigrator(connectionString => new DbSchemaImporter(connectionString, TestResources.dbscript)) .BeforePersisting((ctx, entity) => { beforePersistingCalled = true; Assert.IsNotNull(ctx); Assert.IsInstanceOf <CommunicatorContext>(ctx); Assert.IsNotNull(entity); Assert.IsInstanceOf <COMBlockListReason>(entity); }) .AfterPersisting((before, after) => { afterPersistingCalled = true; Assert.IsNotNull(before); Assert.IsNotNull(after); Assert.AreNotEqual(before, after); before.GetType().ShouldBeAssignableFrom <COMBlockListReason>(); }) .ShouldPersistAndRecall(); //---------------Test Result ----------------------- Assert.IsTrue(beforePersistingCalled); Assert.IsTrue(afterPersistingCalled); }
public void WhenMigrationsCreateEntitiesButRunBeforeClearsThemOut_ShouldNotFailBecauseOfExistingEntities() { //---------------Set up test pack------------------- using (var db = new TempDBLocalDb()) { //---------------Assert Precondition---------------- //---------------Execute Test ---------------------- Assert.DoesNotThrow(() => EntityPersistenceTester.CreateFor <SomeEntityWithDecimalValue>() .WithContext <EntityPersistenceContext>() .WithDbMigrator(cs => new DbSchemaImporter(cs, ENTITY_PERSISTENCE_CONTEXT_WITH_DATA_SQL)) .WithSharedDatabase(db) .BeforePersisting((ctx, entity) => { ctx.EntitiesWithDecimalValues.Clear(); ctx.SaveChangesWithErrorReporting(); }) .ShouldPersistAndRecall() ); //---------------Test Result ----------------------- } }