在 VS 2013 的 C# 代码测试方法中有效使用 Shim

valid use of Shim in a Test Method in VS 2013 for c# code

我有以下测试方法代码:

[TestMethod]        
public void TestWithNotNull()
{            
    using (ShimsContext.Create())
    {
        ShimMyConfiguration.Constructor = @this => new ShimMyConfiguration()
        {
            return;
        };
        ShimMyConfiguration.AllInstances.LoadValuesFromConfigXmlNode = (a,b) =>
        {
            return;
        };
        var _MyConfigurationHandler = new MyConfigurationHandler();
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml("<Common.Mys><Mys><add name=\"LoggingErrorMessage\"/><remove name=\"LoggingMessageBox\"/></Mys></Common.Mys>");          
        var config = _MyConfigurationHandler.Create(null, null, xmlDoc.SelectSingleNode("Common.Mys"));                        
        Assert.IsNotNull(config);
    }           
}

实际Code/Method我正在测试:

public object Create(object parent, object configContext, XmlNode section)
{
    if (section == (XmlNode)null)
        throw new ArgumentNullException("section");

    MyConfiguration config = new MyConfiguration();
    config.LoadValuesFromConfigXml(section);
    return config;
}

我对上述创建方法进行单元测试的方式是否正确?因为我有以下问题:

  1. 我已经填充了构造函数,但没有做实际构造函数 MyConfiguration 会做的事情。是否必须执行实际构造函数所做的事情?如果是这样,我们如何在 ShimMyConfiguration 中实例化 MyConfiguration?

  2. 我填充了 LoadValuesFromConfigXmlNode,但不关心语句 config.LoadValuesFromConfigXml(section) 返回时包含的配置对象。

  3. 由于第 1 点和第 2 点,我只是在测试配置是否不为空。但是这样验证就足够了吗,还是我真的需要针对调用中传递的 xml 内容进行测试 _MyConfigurationHandler.Create(null, null, xmlDoc.SelectSingleNode("Common.Mys")) 返回的是什么?

任何答案都将帮助我评估我是否充分利用了垫片。

就目前而言,您的测试毫无意义。我可以用下面的代码满足测试:

public object Create(object parent, object configContext, XmlNode section)
{
    return new int();
}

如果这是 Create 方法的众多测试之一,那么这不是世界末日,只要其他测试涵盖所需行为的其余部分即可。

根据您发布的方法,我想至少编写以下测试:

  1. 验证如果提供的部分为空,则抛出 ArgumentNullException
  2. 验证提供给您的 Create 调用的部分是否已传递给 MyConfiguration 的实例,并且同一实例是否从 Create 调用返回。

假设测试 1 存在于其他地方,测试 2 可能如下所示:

[TestMethod]        
public void TestMyConfigurationUsedToReadConfiguration()
{            
    MyConfiguration calledOnInstance = null;     
    MyConfiguration returnedInstance = null;
    XmlNode calledWithSection = null;
    XmlNode sectionIn = null;

    using (ShimsContext.Create())
    {
        ShimMyConfiguration.Constructor = @this => new ShimMyConfiguration()
        {
            return;
        };
        ShimMyConfiguration.AllInstances.LoadValuesFromConfigXmlNode = (a,b) =>
        {
            calledOnInstance = a;
            calledWithSection = b;
            return;
        };
        var _MyConfigurationHandler = new MyConfigurationHandler();
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml("<Common.Mys><Mys><add name=\"LoggingErrorMessage\"/><remove name=\"LoggingMessageBox\"/></Mys></Common.Mys>");          
        sectionIn = xmlDoc.SelectSingleNode("Common.Mys");
        returnedInstance = _MyConfigurationHandler.Create(null, null, sectionIn);                 

    }           
    Assert.IsNotNull(returnedInstance);
    Assert.AreEqual(returnedInstance, calledOnInstance);
    Assert.AreEqual(sectionIn, calledWithSection);
}