2015-10-14 8 views
14

Versuchen Sie einige Geschäftslogik in C# durch Überschreiben der EF SaveChanges-Methode.
Die Idee ist es, einige fortgeschrittene Berechnungen über Dinge wie, wenn dieses Feld geändert hat, dieses Feld zu aktualisieren. Und dieses Feld ist die Summe der Unterklasse abzüglich einiger anderer Felder, Sie kennen fortgeschrittenen Geschäftsmüll.Testen von EF Save Changes Modifiers. Übergabe in DbPropertyValues ​​

Da es wirklich kompliziert ist, wollen wir das Ausfüllen testen. Hinzufügen von Tests arbeiten toll, aber die Aktualisierung, die wir scheinen nicht zu testen, da wir eine Schnittstelle geschrieben haben, in dem das betreffende Verfahren übergeben wird Signature

void Update(object entity, DbPropertyValues currentValues, DbPropertyValues originalValues); 

wie diese aussieht, wenn es in voller EF Aufruf funktioniert es schön

public override int SaveChanges() 
    { 
     var added = ChangeTracker.Entries().Where(p => p.State == EntityState.Added).Select(p => p.Entity); 
     var updated = ChangeTracker.Entries().Where(p => p.State == EntityState.Modified).Select(p => p); 

     var context = new ChangeAndValidationContext(); 

     foreach (var item in added) 
     { 
      var strategy = context.SelectStrategy(item); 
      strategy.Add(item); 
     } 

     foreach (var item in updated) 
     { 
      var strategy = context.SelectStrategy(item); 
      strategy.Update(item.Entity, item.CurrentValues, item.OriginalValues); 
     } 
     return base.SaveChanges(); 
    } 

Wir können einfach nicht herausfinden, wie in der DbPropertyValues ​​Original übergeben oder für unsere Tests aktualisiert. Bitte helfen Sie uns herauszufinden, wie Sie diese Methode testen können.

Antwort

4

entschied ich mich der bessere Weg, was die Strategie erwartet zu ändern war. Statt

void Update(object entity, DbPropertyValues currentValues, DbPropertyValues originalValues); 

Ich habe es akzeptieren

void Update(object entity, Dictionary<string, object> currentValues, Dictionary<string, object> originalValues); 

Was bedeutete, dass ich die Werte in die Update-Methode übergeben geändert

foreach (var item in updated) 
{ 
     var strategy = context.SelectStrategy(item); 
     strategy.Update(item.Entity, item.CurrentValues.ValuesToValuesDictionary(), item.OriginalValues.ValuesToValuesDictionary()); 
} 

Dann habe ich diese Erweiterung Methode

public static class DbPropertyValueExtensions 
{ 
    public static Dictionary<string, object> ValuesToValuesDictionary(this DbPropertyValues vals) 
    { 
     var retVal = new Dictionary<string, object>(); 
     foreach (var propertyName in vals.PropertyNames) 
     { 
      if (!retVal.ContainsKey(propertyName)) 
      { 
       retVal.Add(propertyName, vals[propertyName]); 
      } 

     } 
     return retVal; 
    } 
} 

Was bedeutete dass meine Tests in diesen Wörterbüchern bestanden haben.

[Test] 
    public void DateLastModifiedUpdatesOnUpdate() 
    { 
     //Arrange 
     var toTest = LossFactoryHelper.Create(); 
     var lossCheckAndValidationAddStrategy = new LossChangeAndValidationStrategy(); 
     var now = DateTime.UtcNow; 
     var originalValues = toTest.GetValuesNow(); 
     //Act 


     toTest.mny_deductible = -1; 
     var currentValues = toTest.GetValuesNow(); 
     lossCheckAndValidationAddStrategy.Update(toTest, originalValues, currentValues); 

     //Assert 
     Assert.GreaterOrEqual(toTest.clc_DateLastModified, now); 
    } 

und die Erweiterung Methode, um das Wörterbuch über und über

public static class ReflectionToGetCurrentValuesExtension 
{ 
    public static Dictionary<string, object> GetValuesNow(this object obj) 
    { 
     var retVal = new Dictionary<string, object>(); 
     var type = obj.GetType(); 
     PropertyInfo[] properties = type.GetProperties(); 
     foreach (PropertyInfo property in properties) 
     { 
      if (property.CanRead && property.CanWrite) 
      { 
       if (!retVal.ContainsKey(property.Name)) 
       { 
        retVal.Add(property.Name, property.GetValue(obj)); 
       } 
      } 
     } 
     return retVal; 
    } 
} 
zu haben nicht einen Schnappschuss der Werte zu erhalten erstellen
5

Wenn Sie über Visual Studio 2012 Update 2+ verfügen, können Sie die Option "Fälschung hinzufügen" für EntityFramework hinzufügen, indem Sie in Ihrem Testprojekt mit der rechten Maustaste auf die Projektreferenz klicken.

Einmal hinzugefügt, können Sie Instanzen von System.Data.Entity.Infrastructure.Fakes.ShimDbPropertyValues erstellen, die vollständig unter Ihrer Kontrolle sind. z.B.

var shim = new System.Data.Entity.Infrastructure.Fakes.ShimDbPropertyValues(); 
shim.ItemGetString = s => "Hello, World!"; 

Und wenn GetString auf diesem gefälscht/Shim genannt wird DbPropertyValues es wird wieder "Hallo, Welt!".

Weitere Details hier: https://msdn.microsoft.com/en-us/library/hh549175.aspx