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.