【问题标题】:How to test method with 'out' parameter(s)?如何使用“out”参数测试方法?
【发布时间】:2025-12-15 00:30:02
【问题描述】:

我正在尝试为没有参数的方法编写单元测试。我的方法特别是我的自定义对象的 TryParse 方法。我在 Visual Studio 2013 中使用 .NET 4.5/5。这使我能够使用 PrivateType 对象完全实现私有/内部和静态对象。似乎让我无法理解的一件事是如何测试 out 参数,因为我不能在 InvokeStatic 方法中使用这个关键字。我正在寻找合适的解决方案来测试这个架构设计。

TryParse 的使用是 TypeConverter 进程的一部分,如 WebAPI Parameter Binding post By Mike Wilson 中所述

public class MyFilter
{
    public string Field { get; set; }
    //... removed for brevity

    internal static bool TryParse(string sourceValue, out MyFilter filter)
    {
        //... removed for brevity
    }
}

public class MyFilterTests
{
    [TestMethod]
    [TestCategory("TryParse")]
    public void TryParseWithTitleOnly()
    {
        var stringSource = "{field:'DATE.FIELD'}";

        MyFilter tryParseOut = null;

        var target = new PrivateType(typeof(MyFilter));

        var tryParseReturn = target.InvokeStatic("TryParse", stringSource, tryParseOut);

        var expectedOut = new MyFilter()
        {
            Field = "DATE.FIELD"
        };

        Assert.IsTrue((bool)tryParseReturn);
        Assert.AreEqual(expectedOut, tryParseOut);
    }
}

【问题讨论】:

  • 而 TryParse 必须是内部的?
  • 因为架构设计是为了限制对外部不需要的属性的访问(关注点分离)。这迫使我们的开发人员在处理数据对象时使用正确的编码模式。

标签: c# unit-testing out


【解决方案1】:

就我个人而言,我会使用InternalsVisibleTo 以使该方法对您的测试代码可见,但如果您确实想使用PrivateType,我希望您能够只需创建一个您保留引用的object[],将其传递给InvokeStatic,然后再次获取该值:

object[] args = new object[] { stringSource, null };
var tryParseReturn = target.InvokeStatic("TryParse", args);

...

// args[1] will have the value assigned to the out parameter
Assert.AreEqual(expectedOut, args[1]);

至少,我希望 这样做 - 这就是反射通常处理 ref 和 out 参数的方式。

【讨论】:

  • args 没有传递给 InvokeStatic 或者我遗漏了什么?
  • @haim770 InvokeStatic 有几个接口,我尝试在这种情况下使用的接口记录在这里。 msdn.microsoft.com/en-us/library/ms244026.aspx
  • @JonSkeet 谢谢,这实际上是我应该做的。我全神贯注于以这种方式测试所有其他静态进程,我忘记了我可以为“内部”进程执行此操作以与其他程序集结为“朋友”。
  • @JonSkeet 提出的解决方案
  • @haim770 是的 Jon Skeet 的解决方案有效。我没有 IComparer,所以我必须明确评估我的 Assert.IsEqual(expected, actual),否则测试现在正在运行。