嗨!
我有一个看起来像这样的课程:
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的东西[我认为其他人已经完成了这个:)]我只想测试方法是否正确返回默认项的值或关于参数的导入项目)
这是我的问题。我可以创建一个测试来检查默认值但是我无法使用特定“权限”的存根创建测试,假设目录(对于DirectoryCatalog)为空。那么有没有办法从测试方法“注入”Stub [IKnownAuthority]到allready组成的目录?
我尝试过这样的事情:
[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。我确信这只是一个理解上的问题,但我无法弄清楚......
答案 0 :(得分:0)
以您尝试的方式合并两个容器是不可能的。每当您调用ItemsCollector
的构造函数时,您都会创建一个CompositionContainer
并调用Compose / ComposeParts。这会导致MEF从您提供的目录中构建其内部结构,以便在您提出要求时能够为您提供正确的值。但是,既然您在单元测试中说您的DirectoryCatalog为空,MEF将找不到任何导出来填充您的导入。
如果您的单元测试第二个CompositionContainer
,您将提供已构建的ItemsCollector
实例。这会导致MEF不为它解析任何导入,而只是将其作为给定的。
因此,如果你想坚持使用CompositionContainer
ItemsCollector
封装{@ 1}}你唯一的方法进行单元测试就可以在两种情况下都填充该目录。
另一种选择是将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类型,请创建自己的类型来包装目录。
希望这会有所帮助 - 如果您认为可以更好地解释它,将提供代码。