使用nUnit对通用扩展方法进行单元测试

时间:2017-06-30 09:29:04

标签: c# unit-testing generics

我将扩展方法写入XElement类,然后我想测试它,但是我在单元测试中调用它时遇到了困难。我也想让测试通用。

这是方法,AsBoolean是字符串的简单扩展并不重要:

/// <summary>
///     Safely gets value from attribute.
/// </summary>
/// <typeparam name="T"> Return type.</typeparam>
/// <param name="xElem"><see cref="XElement"/> in which attribute will be searched.</param>
/// <param name="attrName"> Name of the attribute that is going to be searched. </param>
/// <param name="defaultValue"> Default value of the return value. </param>
/// <param name="throwExceptions"> Determines if this method will throw exceptions. </param>
/// <returns> Converted value to type <see cref="T"/></returns>
public static T SafeGetValue<T>(this XElement xElem, string attrName, T defaultValue = default(T), bool throwExceptions = false)
{
    // Sets up default value for result
    var result = defaultValue;
    var value = xElem.Attribute(attrName)?.Value;

    if (value == null) { return result; }

    try
    {
        // Treats boolean type a bit differently as .NET converter is a bit harsh.
        if (typeof(T) == typeof(bool))
        {
            // Converts string to boolean using custom extension
            result = (T) Convert.ChangeType(value.ToBoolean(), typeof(T));
            return result;
        }

        result = (T) Convert.ChangeType(value, typeof(T));
        return result;
    }
    catch (InvalidCastException ex)
    {
        Logger.LogManager.GetLogger($"{nameof(XElementExtensions)} " +
                                        $"threw {ex} because it can't convert {value} to type {typeof(T)}");
        if (throwExceptions)
        {
            throw;
        }
    }
    catch (Exception ex)
    {
        Logger.LogManager.GetLogger($"{nameof(XElementExtensions)} threw {ex}!");

        if (throwExceptions)
        {
            throw;
        }
    }

    return result;
}

现在我想这样测试一下:

[TestFixture]
public class SafeGetValueTests
{
    private XDocument _doc;

    [SetUp]
    public void Setup()
    {
         _doc = XDocument.Parse(@"
          <root>
           <bool></bool>
           <int></int>
           <string></string>
           <double></double>
           <decimal></decimal>
           <datetime></datetime>
          </root>
        "); 
    }

    [TestCase("bool","boolAttr", 234235, typeof(bool))]
    [TestCase("bool", "boolAttr", "dsfgdf", typeof(bool))]
    [TestCase("bool", "boolAttr", 234235, typeof(bool))]
    public void SafeGetValueShouldReturnDefaultValueWhenInvokedWithTypeThatCannotBeConvertedToTheValue(
        string elementName, string attrName, object attrValue, Type type)
    {
        //Arrange
        _doc.Element(elementName)?.SetAttributeValue(attrName, attrValue);
        var genericMethod = typeof(XElementExtensions).GetMethod("SafeGetValue");
        genericMethod = genericMethod.MakeGenericMethod(type);
        //Act
        var value = genericMethod.Invoke(_doc.Element(elementName), 
            BindingFlags.OptionalParamBinding | 
            BindingFlags.InvokeMethod |
            BindingFlags.Static, 
            null, 
            new[] {attrName , Type.Missing, Type.Missing},
            CultureInfo.InvariantCulture);

        //Assert
        Assert.AreEqual(value, default(bool));
    }
}

但调用仍然失败:

  

mscorlib.dll中发生了'System.Reflection.TargetParameterCountException'类型的异常,但未在用户代码中处理。附加信息:参数计数不匹配。

如何测试这种情况?

1 个答案:

答案 0 :(得分:1)

SafeGetValue需要4个参数,在调用中你传递3:

new[] {attrName , Type.Missing, Type.Missing},

您缺少第一个参数XElement

可能你想传递

new[] {_doc.Element(elementName), attrName , Type.Missing, Type.Missing},