20

単体テスト用のモッキング フレームワークとして Rhino Mocks を使用しています。

テストしたいクラスである Subject というクラスがあります。IStore に依存しています。

IStore は次のように定義されます。

//internal interface : has InternalsVisible to both "Subject" 
//and "StoreTests" class namespaces
internal interface IStore {
    void Store(string name);
    //other methods
}

Subject クラスは次のように定義されます。

class Subject : IStore {
    private IStore internalStore;

    //constructor injection
    void Subject(IStore store) {
        internalStore = store;
    }

    void Store(string name) {
        internalStore.Store(name);
    }

    //other methods
}

RhinoMocks を使用した私のテスト クラスは次のとおりです。

//test class
class StoreTests {
    Subject subject = new Subject();

    [Test]
    public StoreTest() {
        //Arrange
        var mockStore = MockRepository.GenerateMock<IStore>();
        string testName = "test";
        mockStore.Expect(x => x.Store(testName)).Returns(null);

        //Act
        subject.Store(testName);

        //Assert
        mockStore.VerifyAllExpectations();
    }

    //other test methods
}

私の設定では、インターフェイスは internal として定義されており、Subject クラスと StoreTests クラスの両方に InternalsVisible が設定されています。ただし、テスト ケースが実行されると、var mockStore = MockRepository.GenerateMock(); で例外がスローされます。IStore は公開されていないため、モックを生成できませんでした。

これは、IStore が公開されていないためだと思います。しかし、IStore dll に InternalsVisibleTo を設定したので、StoreTests がそのクラスのモックを作成するには十分ではないでしょうか?

この問題は、IStore インターフェイスを公開することで解決できるのではないかと考えています。ただし、これは私にとっては選択肢ではないため、 IStore のモックを作成できる他の方法はありますか?

4

3 に答える 3

36

アセンブリの内部を Rhino モックから見えるようにしてみましたか?

[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]

詳細については、 Rhino モックの内部メンバーを参照してください。

クラスがモックされると、モックされたクラスから派生した新しいクラスが実行時に生成されます。この生成されたクラスは、「DynamicProxyGenAssembly2」と呼ばれる別の「一時」アセンブリに存在します。そのため、InternalsVisibleTo 属性をターゲット アセンブリに設定して、一時アセンブリからその内部メンバーにアクセスできるようにする必要があります。それ以外の場合、モック オブジェクトは内部メンバーにアクセスできないため、内部メンバーをオーバーライドできません(これが、モックされたメソッドを仮想としてマークする必要がある理由でもあります)。これは、単体テストとテスト対象のクラスが同じアセンブリにある場合でも当てはまることに注意してください。

そのため、ターゲット クラスのアセンブリがその内部をプロキシ アセンブリから見えるようにする必要があります (たとえば、AssemblyInfo.cs 内)。

于 2011-07-28T08:11:29.067 に答える
11

はい、テスト中のアセンブリのAssemblyInfo.csファイルに以下を追加するだけで十分です。

[assembly: InternalsVisibleTo("Tests.Assembly.Name")]
[assembly: InternalsVisibleTo("NUnit.Framework")]
[assembly: InternalsVisibleTo("Rhino.Mocks, PublicKey=00240000048000009400000006020000002400005253413100040000010001009D1CF4B75B7218B141AC64C15450141B1E5F41F6A302AC717AB9761FA6AE2C3EE0C354C22D0A60AC59DE41FA285D572E7CF33C320AA7FF877E2B7DA1792FCC6AA4EB0B4D8294A2F74CB14D03FB9B091F751D6DC49E626D74601692C99EAB7718ED76A40C36D39AF842BE378B677E6E4EAE973F643D7065241AD86ECC156D81AB")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
于 2011-07-28T08:09:13.060 に答える
3

これは答えられるかもしれませんが、私にとってはうまくいきませんでした。

それで、これを機能させるために私がしたことは次のとおりです(次のプロジェクトで他の人、さらには私を助けるかもしれません....):

Visual Studio の [ツール] メニュー: 外部ツール: 名前に「LongStrongName」を追加しますが、自分に合うものを何でも入力します:

(このパス、または sn.exe がある場所):

Command:
  C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\sn.exe
Arguments:
  -Tp $(TargetPath)

(チェックボックスをクリックし、「出力ウィンドウを使用」に出力)

これで、プロジェクトをクリックして、ツールに移動し、[LongStrongName] メニューに移動できます。

そしてVSは出力します:

Public key is       0240000048000009400000006020000002400005253413100040000010001009badbe86c32ec0
ec429f0b3909*********

Public key token is 6ccc051********

assembly.cs を開き、以下を追加します。

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

必要なアセンブリを追加してください(複数のアセンブリを配置する必要がありました)。

于 2012-08-03T19:12:21.070 に答える