【问题标题】:Unit Testing ref structs with private fields via Reflection通过反射对具有私有字段的引用结构进行单元测试
【发布时间】:2019-09-16 14:41:25
【问题描述】:

我实现了一对 ref 结构并想为它们编写一些单元测试。自然,所有字段都是私有的。假设 API 不应该显示类的内部工作原理,我如何在某些操作后测试字段是否具有正确的值?我想避免修改 ref 结构本身只是为了适应测试。

我的第一个选择是反射,以访问私有字段,但这种方法的问题是我无法让它访问 ref 结构,因为我必须在某个对象中将它装箱点,或将其用作泛型类型参数(这对于 ref 结构也是非法的)。

是否有一些代码生成库或可以做到这一点的东西,或者我错过了其他一些方法/解决方案?

【问题讨论】:

  • 我知道我在这里为“框架挑战”敞开心扉,但是“不要那样做”的答案对我没有多大帮助。这个类需要大量的测试,而且它需要完全坚如磐石。我需要知道它的内部值是正确的。
  • 你能展示任何要测试的课程吗?

标签: c#


【解决方案1】:

ref 结构不能用作泛型类型参数,但这可以通过预定义的委托类型来解决。

这可能是不明智的,但它似乎确实有效:

using System.Linq.Expressions;

public static TDelegate CreateAccessor<TDelegate>(string memberName) where TDelegate : Delegate
{
    var invokeMethod = typeof(TDelegate).GetMethod("Invoke");
    if (invokeMethod == null)
        throw new InvalidOperationException($"{typeof(TDelegate)} signature could not be determined.");

    var delegateParameters = invokeMethod.GetParameters();    
    if (delegateParameters.Length != 1)
        throw new InvalidOperationException("Delegate must have a single parameter.");

    var paramType = delegateParameters[0].ParameterType;

    var objParam = Expression.Parameter(paramType, "obj");
    var memberExpr = Expression.PropertyOrField(objParam, memberName);
    Expression returnExpr = memberExpr;
    if (invokeMethod.ReturnType != memberExpr.Type)
        returnExpr = Expression.ConvertChecked(memberExpr, invokeMethod.ReturnType);

    var lambda = Expression.Lambda<TDelegate>(returnExpr, $"Access{paramType.Name}_{memberName}", new [] { objParam });
    return lambda.Compile();
}

用法:

ref struct Foo
{
    private string A;
    private int B;

    public Foo(string a, int b)
    {
        A = a;
        B = b;
    }
}

delegate object FooAccessor(Foo foo);
// or
delegate T FooAccessor<T>(Foo foo);

var foo = new Foo("abc", 123);
var a = CreateAccessor<FooAccessor<string>>("A")(foo);
var b = CreateAccessor<FooAccessor<int>>("B")(foo);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 2016-10-25
    • 2015-07-08
    • 2020-12-03
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 2015-04-12
    相关资源
    最近更新 更多