如果调用外部库的方法,则使用Moq进行测试

时间:2013-08-03 13:48:04

标签: c# unit-testing moq

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

用moq嘲笑它并不起作用,因为该方法不是虚拟的。我发现了一些方法可以做到这一点但是所有这些都让我改变了CompositeContainer类,这是我做不到的。

有没有办法在moq中测试是否调用外部第三方库的非虚方法?

提前感谢您的回复。

示例代码:

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

3 个答案:

答案 0 :(得分: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属性将新实现归属,并确保您的类在发生更改时正确地进行更改。

答案 1 :(得分:0)

你班上实施的Load方法?你有没有考虑从那里删除它?考虑到单一责任原则,看起来你的班级做得太多了。

我建议你分割功能 - 你的类会做任何需要做的业务逻辑。还有另一个“基础”类,它负责组合容器 - 在你的情况下获取你的类的实例,并在容器中注册它。

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

答案 2 :(得分:0)

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

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

这里的负面消息是您正在创建一个界面来隐藏原始实现没有为您实现的实例。

示例代码现在是:

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

有一些其他项目的例子将问题包装在.NET框架中的测试类中,例如SystemWrapper