2015-10-14 6 views
14

Próba zrobienia logiki biznesowej w języku C# przez przesłonięcie metody EF SaveChanges.
Chodzi o to, aby mieć pewne zaawansowane obliczenia na temat takich rzeczy, jak gdyby pole to zmieniło aktualizować to pole. To pole jest sumą podklasy minus kilka innych pól, znasz zaawansowane śmieci biznesowe.Testowanie EF Zapisz zmiany w modyfikatorach. Przekazywanie w DbPropertyValues ​​

Ponieważ jest to bardzo skomplikowane, chcemy przetestować to wypychanie. Dodawanie testy działają świetnie ale te aktualizujące nie możemy wydawać przetestować jak pisaliśmy interfejs gdzie omawiana metoda jest przekazywana Podpis wygląda następująco

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

Kiedy nazywając ją w pełnej EF to działa pięknie

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(); 
    } 

Po prostu nie możemy wymyślić, jak przekazać oryginał lub zaktualizować DbPropertyValues ​​dla naszych testów. Pomóż nam dowiedzieć się, jak przetestować tę metodę.

Odpowiedz

4

postanowiłem lepszym sposobem było zmienić to, co strategia oczekiwano. Zamiast

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

Zrobiłem to zaakceptować

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

Oznaczało Zmieniłem wartości przekazywane do metody Aktualizacja

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

Potem stworzył tę metodę rozszerzenia

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; 
    } 
} 

Co znaczy że moje testy musiały przechodzić w tych słownikach.

[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); 
    } 

A metoda Extension, aby pomóc dostać migawkę wartości, aby nie trzeba tworzyć słownika kółko

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; 
    } 
} 
5

Jeśli masz Visual Studio 2012 Update 2+, możesz "Dodaj podróbki Assembly" dla EntityFramework, klikając prawym przyciskiem myszy odniesienie do projektu w projekcie testowym.

Po dodaniu można tworzyć wystąpienia System.Data.Entity.Infrastructure.Fakes.ShimDbPropertyValues, które są całkowicie pod Twoją kontrolą. na przykład

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

A kiedy GetString nazywany jest na tym fałszywym/podkładki DbPropertyValues powróci "Hello, World!".

Więcej szczegółów tutaj: https://msdn.microsoft.com/en-us/library/hh549175.aspx