2

単体テストを実装しているVisualStudio2008 C#.NET 3.5プロジェクトがありますが、問題が発生しました。私のコードは、内部コンストラクターを使用してオブジェクトを実装するサードパーティのアセンブリを参照しています。

例えば:

// in 3rd party assembly
public class Bar
{
    // internal constructor
    internal Bar();
    public int Id { get; }
    public string Name { get; }
    public Foo Foo { get; }
}

public class Foo
{
    // internal constructor
    internal Foo();
    public Collection<Bar> GetBars();
}

私がユニットテストしたい私の方法の1つはこれです:

// in my assembly
public static Bar FindByName(this Collection<Foo> c, string name)
{
    // search through the Foos to find the first bar with the matching name
}

そして、次のようにテストします。

void TestMethod()
{
    Collection<Foo> foo_pool = new Collection<Foo>()
    {
        new Foo() { /*..*/ } // Error! ctor is inaccessible
    };

    Bar b = foo_pool.FindByName("some_name");
    assert_equal (b.Name, "some_name");
}

Fooしかし、タイプまたはタイプのオブジェクトを作成することはできませんBar。では、どうすればメソッドをユニットテストできますか?

ありがとう

4

3 に答える 3

3

単体テストの場合、PrivateObjectクラス(名前空間Microsoft.VisualStudio.TestTools.UnitTesting)を使用して、プライベートコンストラクターを使用してオブジェクトを作成し、プライベートメソッドをテストすることもできます。

http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privateobject(v=vs.90).aspx

http://www.gangleri.net/2007/11/15/PrivateObjects.aspx

次に例を示します。

[TestMethod]
public void TestMethod2()
{
    // Arrange
    var po = new PrivateObject(typeof(MyObject));
    var obj = (MyObject)po.Target;
    // Act
    var result = obj.Calculate(2);
    // Assert
    Assert.AreEqual(3, resul);
}

public class MyObject
{
    internal MyObject()
    {

    }

    public int Calculate(int a)
    {
        return 1 + a;
    }
}

Jimの提案と同じ方法でリフレクションを使用しますが、PrivateObjectクラスは、プライベートコンストラクターを使用してインスタンスを作成するためのすべての作業をカプセル化します。

于 2012-04-05T16:46:10.987 に答える
1

リフレクションを使用して、非公開コンストラクターでオブジェクトを作成できます。SOでこの質問を参照してください。

上記のリンクからのAniの解決策は次のとおりです。

BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
 CultureInfo culture = null; // use InvariantCulture or other if you prefer
 object instantiatedType =   
   Activator.CreateInstance(typeToInstantiate, flags, null, parameter, culture);

Activator.CreateInstanceは、指定したパラメーターに基づいて正しいコンストラクターを検索します。

于 2012-04-05T16:32:55.693 に答える
0

クラスが封印されていない/継承できない場合は、テストターゲットクラスから「モック」クラスを派生させ、独自のコンストラクターを追加できます。テストしている基本メソッドを変更しない限り、これは機能するはずです。

例えば:

public class MyBar:Bar
{
    // internal constructor
    public MyBar(object throwaway)
    {
       //call base constructor if necessary
    };
    public int Id { get; }
    public string Name { get; }
    public Foo Foo { get; }
}
于 2012-04-05T16:45:51.517 に答える