簡體   English   中英

在 C# 中測試私有靜態泛型方法

[英]Testing private static generic methods in C#

如何測試私有靜態泛型方法? 內部結構對我的測試項目可見。 如何測試這些方法?

internal class Foo {

    // Non-static.  This works!
    private T TestThisMethod1<T>(T value) {
        Console.WriteLine("Called TestThisMethod1");
        return value;
    }

    // Static.  Can't get this to work!
    private static T TestThisMethod2<T>(T value) {
        Console.WriteLine("Called TestThisMethod2");
        return value;
    }

    // Static.  Can't get this to work!
    private static void TestThisMethod3<T>(T value) {
        Console.WriteLine("Called TestThisMethod3");
    }

    // Static.  Can't get this to work!
    private static void TestThisMethod4<T, T2>(T value, T2 value2) {
        Console.WriteLine("Called TestThisMethod4");
    }
}

第一個例子有效。 它不是靜態的。 這是來自https://msdn.microsoft.com/en-us/library/bb546207.aspx的示例。

[TestMethod]
public void PrivateStaticGenericMethodTest() {

    int value = 40;
    var foo = new Foo();

    // This works.  It's not static though.
    PrivateObject privateObject = new PrivateObject(foo);
    int result1 = (int)privateObject.Invoke("TestThisMethod1", new Type[] { typeof(int) }, new Object[] { value }, new Type[] { typeof(int) });

    // Fails
    int result2 = (int)privateObject.Invoke("TestThisMethod2",  BindingFlags.Static | BindingFlags.NonPublic, new Type[] { typeof(int) }, new Object[] { value }, new Type[] { typeof(int) });

    // Fails
    PrivateType privateType = new PrivateType(typeof(Foo));
    int result2_1 = (int)privateType.InvokeStatic("TestThisMethod2", new Type[] { typeof(int) }, new Object[] { value }, new Type[] { typeof(int) });

    // Fails
    int result2_2 = (int)privateType.InvokeStatic("TestThisMethod2", BindingFlags.Static | BindingFlags.NonPublic, new Type[] { typeof(int) }, new Object[] { value }, new Type[] { typeof(int) });

    // Stopping here.  I can't even get TestThisMethod2 to work...
}

我寫這篇文章的目的並不是真正質疑或辯論測試私有方法的優點:這個問題已經被反復辯論過。 更重要的是,我寫這個問題的目的是說“應該可以使用 PrivateObject 或 PrivateType 來做到這一點。那么,怎么做呢?”

終於找到了一種方法來通過谷歌搜索使用泛型類型進行測試。 使用它自己請求的對象,然后運行 ​​make 通用方法調用並最后調用它。

[TestMethod]
public void TestMethod2()
{
    int value = 40;
    var foo = new Foo();

    MethodInfo fooMethod = foo.GetType().GetMethod("TestThisMethod2", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance);
    if (fooMethod == null)
    {
        Assert.Fail("Could not find method");
    }
    MethodInfo genericFooMethod = fooMethod.MakeGenericMethod(typeof(int));
    int result1 = (int)genericFooMethod.Invoke(typeof(int), new object[] { value });

    Assert.AreEqual(result1, value);
}

您不應該測試私有方法。 因為它們是可以更改的實現細節。 您應該測試您的公共接口。

如果您在覆蓋公共接口后有未覆蓋的私有方法,請將其刪除。

通過我的測試,PrivateObject 似乎在靜態和通用方法方面存在問題。 依靠布賴恩的回答,這是一種您可以使用(和修改)的方法。

public static class PrivateMethodTester
{
    public static object InvokePrivateMethodWithReturnType<T>(T testObject, string methodName, BindingFlags flags, Type[] genericTypes, object[] parameters) {
        MethodInfo methodInfo = testObject.GetType().GetMethod(methodName, flags);
        if (methodInfo == null) {
            throw new Exception("Unable to find method.");
        }
        MethodInfo method = methodInfo.MakeGenericMethod(genericTypes);
        return method.Invoke(genericTypes, parameters);
    } 
}

像這樣調用它:

            Type[] types = new Type[] { typeof(MyGenericType1) };
            var parameters = new object[] { new MyClassParam(), "stringParam" };
            var returnObj = PrivateMethod.InvokePrivateMethodWithReturnType(new TestObjectClass("fake", null), "MyPrivateMethodName", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance, types, parameters);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM