如何使用Moq满足MEF导入依赖项进行单元测试?

4
这是我的界面。
public interface IWork
{
    string GetIdentifierForItem(Information information);
}

和我的班级

public class A : IWork
{
[ImportMany]
public IEnumerable<Lazy<IWindowType, IWindowTypeInfo>> WindowTypes { get; set; }

public string GetIdentifierForItem(Information information)
{
    string identifier = null;
    string name = information.TargetName;

    // Iterating through the Windowtypes 
    // searching the 'Name' and then return its ID  
    foreach (var windowType in WindowTypes)
    {
        if (name == windowType.Metadata.Name)
        {
            identifier = windowType.Metadata.UniqueID;
            break;
        }
    }
    return identifier;
}
}
问题:我想对GetIdentifierForItem方法进行单元测试。

以下是我尝试解决它的方式 -

(1) 创建一个Mock的Lazy对象并设置其需要返回的属性值:

var windowMock = new Mock<Lazy<IWindowType, IWindowTypeInfo>>(); windowMock.Setup(foo => foo.Metadata.Name).Returns("Data"); windowMock.Setup(foo => foo.Metadata.UniqueID).Returns("someString");

(2) 创建一个窗口类型列表和上述模拟对象,然后将其设置给创建的A对象。

var WindowTypesList = new List<IWindowType, IWindowTypeInfo>>();
WindowTypesList.Add(windowMock.Object);
A a = new A();
a.WindowTypes = WindowTypesList;

(3) 创建信息模拟数据

var InfoMock = new Mock<Information>();
InfoMock.Setup(foo => foo.TargetName).Returns("Data");

将以上内容作为单元测试整合如下:
[TestMethod]
public void GetIDTest()
{
    var windowMock = new Mock<Lazy<IWindowType, IWindowTypeInfo>>();
    windowMock.Setup(foo => foo.Metadata.Name).Returns("Data");
    windowMock.Setup(foo => foo.Metadata.UniqueID).Returns("someString");

    var WindowTypesList = new List<Lazy<IWindowType, IWindowTypeInfo>>();
    WindowTypesList.Add(windowMock.Object);

    A a = new A();
    a.WindowTypes = WindowTypesList;
    var InfoMock = new Mock<Information>();
    InfoMock.Setup(foo => foo.TargetName).Returns("Data");

    string expected = "someString"; // TODO: Initialize to an appropriate value
    string actual;
    actual = a.GetIdentifierForItem(InfoMock.Object);
    Assert.AreEqual(expected, actual);

}

这个单元测试执行失败并抛出了一个'TargetInvocationException'异常,查看详细信息,似乎我在做一些不应该做的事情。

但我不确定如何以其他方式进行。我已经阅读了Moq的快速入门指南中的一些链接。我知道我缺少了一些东西。你能通过指导我如何进行单元测试来帮助我吗?

2个回答

6
这是一个示例,展示了如何在设置模拟后完成以下操作:
1)创建CompositionContainer来保存导入项。
2)将模拟数据添加到容器中。
container.ComposeExportedValue(mock.Object);

3) 创建被测试类的实例

4) 组合模拟对象以进行导入

container.ComposeParts(instance);

2

您不需要Mock Lazy<T,TMetadta>。它足够灵活,可以与您的测试一起使用。相反,Mock IWindowTypeInfo

[TestMethod]
public void GetIDTest()
{
    var windowTypeInfoMock = new Mock<IWindowTypeInfo>();
    windowTypeInfoMock.Setup(foo => foo.Name).Returns("Data");
    windowTypeInfoMock.Setup(foo => foo.UniqueID).Returns("someString");
    var lazyWindow =
         new Lazy<IWindowType, IWindowTypeInfo>(windowTypeInfoMock.Object);

    var WindowTypesList = new List<Lazy<IWindowType, IWindowTypeInfo>>();
    WindowTypesList.Add(lazyWindow);

    var a = new A();
    a.WindowTypes = WindowTypesList;
    var InfoMock = new Mock<Information>();
    InfoMock.Setup(foo => foo.TargetName).Returns("Data");

    string expected = "someString";
    string actual;
    actual = a.GetIdentifierForItem(InfoMock.Object);
    Assert.AreEqual(expected, actual);
}

你的测试在我的机器上通过了,只需要做一些小的修改,你不需要为这个测试使用组合容器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接