2

对于一个项目,我使用 MEF 框架的 CompositeContainer 类。现在我想做一个单元测试(使用起订量)来验证是否调用了 ComposeParts(这是 AttributedModelServices 中的扩展方法)方法。

仅仅用 moq 模拟它是行不通的,因为该方法不是虚拟的。我找到了一些方法来做到这一点,但所有这些都让我改变了 CompositeContainer 类,这是我做不到的。

起订量中有没有办法测试是否调用了外部 3rd 方库的非虚拟方法?

提前感谢您的回复。

示例代码:

public void Load(string path, CompositionContainer container)
{           
    container.ComposeParts(this);           
}

这里的容器来自 MEF 库, ComposeParts 是 System.ComponentModel.Composition 命名空间中的扩展方法:

//
// Summary:
//     Creates composable parts from an array of attributed objects and composes
//     them in the specified composition container.
//
// Parameters:
//   container:
//     The composition container to perform composition in.
//
//   attributedParts:
//     An array of attributed objects to compose.
public static void ComposeParts(this CompositionContainer container, params object[] attributedParts);
4

3 回答 3

1

我不相信可以直接验证是否使用 Moq 调用了第三方库方法,但您可以检查调用该方法的副作用。由于您使用 MEF 在运行时检索您的实现,因此我将测试您的类型是否已正确加载。所以如果你有这样的事情:

public interface IInterfaceToCompose
{
    string MethodToCreate();
}

[Export(typeof(IInterfaceToCompose))]
public class ConcreteImplementation1 : IInterfaceToCompose
{
    public string MethodToCreate()
    {
        return "Implementation 1";
    }
}

[Export(typeof(IInterfaceToCompose))]
public class ConcreteImplementation2 : IInterfaceToCompose
{
    public string MethodToCreate()
    {
        return "Implementation 2";
    }
}

然后,您可以编写如下所示的测试:

[ImportMany(typeof(IInterfaceToCompose))]
public IInterfaceToCompose ComposedItems { get; set; }

[Test]
public void WhenComposingTheComposedItems_ShouldLoadExportedTypes()
{
    Load("testPath", YourContainer);

    Assert.AreEqual(2, ComposedItems.Count());
}

您真正想要测试的 (IMO) 是您正确创建了组合类,并且它们都可以由 MEF CompositionContainer 加载。

一个好的第二个测试是进行初始加载,添加一个带有第三个实现者的 dll,并确保最终计数为 3(您的系统是否动态加载新模块)。这将捕获错误,例如忘记使用 Export 属性为新实现赋予属性,并确保您的类在发生更改时正确获取更改。

于 2013-08-06T14:29:54.360 回答
0

它是在您的类中实现的 Load 方法吗?您是否考虑将其从那里删除?考虑到单一职责原则,看起来你的班级做得太多了。

我建议你拆分功能——你的类做它需要做的任何业务逻辑。并有另一个“基础设施”类负责组成容器 - 在您的情况下,获取您的类的实例,并将其注册到容器中。

您将遇到几乎相同的问题,但在另一个地方。而这个“新”的地方将更加专注于它的功能,你可以单独测试它,使用一个真实的容器,并检查它是否组成了正确的部分。

于 2013-08-06T13:57:39.677 回答
0

如果您只想检查一个方法是否被调用,您可以将 CompositionContainer 包装在一个名为 ICompositionContainer 的包装接口中,该接口具有相同的方法签名。然后使用 Moq 你可以断言该方法被调用:

mock.Verify(cc => cc.ComposeParts(), Times.Once());

不利的是,您正在创建一个接口来隐藏原始实现没有为您实现的事实。

示例代码现在是:

public void Load(string path, ICompositionContainer container)
{           
    container.ComposeParts(this);           
}

还有一些其他项目的示例,这些项目将问题包装到 .NET 框架中以测试类,例如SystemWrapper

于 2013-08-06T20:01:23.663 回答