简体   繁体   中英

Unit testing generic extension method with nUnit

I wrote extention method to XElement class and afterwards I wanted to test it , but I am having difficulties with invoking it in my unit test. I also want to make the test generic.

This is the method, AsBoolean is simple extention of string that is not important:

/// <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;
}

Now I want to test it like that :

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

But the invocation keeps failing with:

An exception of type 'System.Reflection.TargetParameterCountException' occurred in mscorlib.dll but was not handled in user code.Additional information: Parameter count mismatch.

How do I test such scenario?

SafeGetValue takes 4 parameters and in invocation you pass 3:

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

You are missing first parameter XElement

Probably you want to pass

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM