2015-10-14 30 views
14

試圖通過覆蓋EF SaveChanges方法在C#中執行一些業務邏輯。
這個想法是有一些高級的計算,如果這個領域已經改變了更新這個領域。這個領域是子類減去其他領域的總和,你知道高級商業垃圾。測試EF保存更改修飾符。傳入DbPropertyValues

由於它非常複雜,我們想測試它的填充。添加測試工作的偉大,但似乎該更新那些我們無法測試,因爲我們已經寫在這裏討論的方法傳遞 簽名看起來像這樣

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

當全EF調用它,它精美的作品

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

我們無法弄清楚如何傳遞DbPropertyValues原始文件或更新測試。請幫助我們弄清楚如何測試該方法。

回答

4

我決定更好的辦法是改變戰略所期望的。取而代之的

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

我把它接受

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

這意味着我改變了傳遞到更新方法

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

值然後我創建的擴展方法

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

這意味着什麼我的測試需要通過這些字典。

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

和擴展方法,以幫助該值不是一個快照必須在創建字典和超過

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

如果您有Visual Studio 2012更新2+,則可以通過右鍵單擊測試項目中的項目引用來爲EntityFramework「添加虛假裝配」。

添加後,您可以創建完全在您控制之下的System.Data.Entity.Infrastructure.Fakes.ShimDbPropertyValues實例。例如

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

GetString上調用,假冒/墊片DbPropertyValues它將返回「你好,世界!」。

更多細節在這裏:https://msdn.microsoft.com/en-us/library/hh549175.aspx