簡體   English   中英

使用MEF導入的C#單元測試方法

[英]C# Unit Test method with MEF Imports

嗨!

我有一堂課,看起來像這樣:

public class ItemCollector {
  public IKnownAuthority _DefaultAuthority = new DefaultAuthority();

  [ImportMany(typeof(IKnownAuthority))]
  private IEnumerable<Lazy<IKnownAuthority, IKnownAuthorityMetadata>> _KnownAuthorities { get; set; }

  public ItemCollector() {
    var catalog = new AggregateCatalog();
    catalog.Catalogs.Add(new DirectoryCatalog(
                Path.Combine(Environment.CurrentDirectory, AUTHORITY_FOLDER)));

    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);
  }

  public IEnumerable<Items> GetItems(string Auth) {
    var Authority = _KnownAuthorities.FirstOrDefault(x => 
                            x.Metadata.AuthorityName.ToLowerInvariant() == 
                            Auth.ToLowerInvariant());

    if (Authority == null)
      return _DefaultAuthority.GetItems(Address);

    return Authority.Value.GetItems(Address);
  }
}

如您所見,有一個方法( GetItems ),我想對該方法進行單元測試。 該方法只是嘗試在MEF容器中查找值,然后返回所找到項目的結果或默認值。 (因此,我不想測試MEF內容[我認為其他人已經准備就緒:)]我只是想測試該方法是否正確返回有關該參數的Default Item或Imported Item的值)

這是我的問題。 我可以創建一個測試來檢查默認值,但是如果目錄(對於DirectoryCatalog)為空,則無法使用存根為特定的“ Authority”創建測試。 那么,有沒有辦法將Stub [IKnownAuthority]“注入”到測試方法中已經准備好的編目中?

我已經嘗試過這樣的事情:

[TestMethod]
public void GetItems_Ok()
{
  ItemsCollector collector = new ItemsCollector();
  collector._DefaultAuthority = new StubDefaultAuthority_01();

  CompositionContainer container = new CompositionContainer();
  container.ComposeExportedValue<IKnownAuthority>(new StubAuthority_02());
  container.ComposeParts(collector);

  var list = collector.GetItems("testing.test"));      
  Assert.IsTrue(list.Count() > 0);
}

[Export(typeof(IKnownAuthority))]
[ExportMetadata("AuthorityName", "testing.test")]
public class StubAuthority_02 : IKnownAuthority
{
  public IEnumerable<Items> GetItems(string Auth) {
    return new List<Items>() { new Items() };
  }
}

StubAuthority_02找不到通往_KnownAuthorities集合的方式。 首先,我認為原因是這樣的事實:我在構造函數中組成了部件,然后又在測試方法中再次組成了(不設置屬性的重組)。 但是,如果我刪除

container.ComposeParts(this);

無論如何,ItemCollector構造函數中的StubAuthority_02行都不存在。 我確信這只是理解上的問題,但我無法弄清楚...

無法以您嘗試的方式合並兩個容器。 每當您調用ItemsCollector的構造函數時,都將創建一個CompositionContainer並調用Compose / ComposeParts。 這將導致MEF從您提供的目錄中構建其內部結構,以便在您索取正確值時為您提供正確的值。 但是由於您在單元測試中說您的DirectoryCatalog為空,所以MEF將找不到任何導出來填充您的導入。

如果您對第二個CompositionContainer單元測試,則將提供已構造的ItemsCollector實例。 這將導致MEF不為其解決任何導入,而只是將其視為給定。

因此,如果要在ItemsCollector中使用CompositionContainer的封裝來堅持該構造,則正確進行單元測試的唯一方法是在兩種情況下都填充該目錄。

另一個選擇是將CompositionContainer移到ItemsCollector之外,然后將目錄提供給容器。 對於您的應用程序代碼和單元測試代碼,目錄將有所不同。

如果您不希望將CompositionContainer移出類,也可以將目錄傳遞給ItemsCollector

... // Your ItemsCollector constructor
public ItemsCollector(ComposablePartCatalog catalog)
{
    var container = new CompositionContainer(catalog);
    Container.Compose(this);
}

如果您使用應用程序,則可以這樣創建收集器實例:

// application code
var directoryCatalog = new DirectoryCatalog(
        Path.Combine(Environment.CurrentDirectory, AUTHORITY_FOLDER));
var collector = new ItemsCollector(directoryCatalog);

在進行單元測試的情況下,您可以執行以下操作:

// unit test code
var catalog = new TypeCatalog(new Type[] {typeof(StubAuthority_02)});
var collector = new ItemsCollector(catalog);

如果您不喜歡自己類型的公共API中的MEF類型,請創建您自己的類型來包裝目錄。

希望這會有所幫助-如果您認為代碼可以更好地解釋它,將提供代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM