【问题标题】:Cannot create a Mock class for an internal type using Rhino Mocks无法使用 Rhino Mocks 为内部类型创建 Mock 类
【发布时间】:2011-10-14 21:36:53
【问题描述】:

我使用 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
}

在我的设置中,接口被定义为内部接口,它为 Subject 类和 StoreTests 类设置了 InternalsVisible。但是,当测试用例执行时,它会在 var mockStore = MockRepository.GenerateMock(); 处引发异常。 说 IStore 不是公开的,因此它无法生成 Mock。

我认为这是因为 IStore 不是公开的。但是,由于我已经在 IStore dll 上设置了 InternalsVisibleTo,所以 StoreTests 为该类创建一个模拟还不够吗?

现在我认为这个问题可以通过公开 IStore 接口来解决。但是,鉴于这对我来说不是一个选项,有没有其他方法可以为 IStore 创建一个模拟?

【问题讨论】:

    标签: c# unit-testing rhino-mocks internal internalsvisibleto


    【解决方案1】:

    是的,在被测程序集的 AssemblyInfo.cs 文件中添加以下内容就足够了:

    [assembly: InternalsVisibleTo("Tests.Assembly.Name")]
    [assembly: InternalsVisibleTo("NUnit.Framework")]
    [assembly: InternalsVisibleTo("Rhino.Mocks, PublicKey=00240000048000009400000006020000002400005253413100040000010001009D1CF4B75B7218B141AC64C15450141B1E5F41F6A302AC717AB9761FA6AE2C3EE0C354C22D0A60AC59DE41FA285D572E7CF33C320AA7FF877E2B7DA1792FCC6AA4EB0B4D8294A2F74CB14D03FB9B091F751D6DC49E626D74601692C99EAB7718ED76A40C36D39AF842BE378B677E6E4EAE973F643D7065241AD86ECC156D81AB")]
    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
    

    【讨论】:

    • 这个答案也很好。将另一个标记为已接受,只是因为它提供了指向 wiki 中其他信息的链接。
    【解决方案2】:

    您是否尝试过让 Rhino 模拟程序可以看到程序集内部?

    [assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]
    

    详情请见Rhino Mocks Internal Members

    当一个类被模拟时,会在运行时生成一个新类,该类派生自模拟类。这个生成的类驻留在一个单独的“临时”程序集中,称为“DynamicProxyGenAssembly2”。因此,需要在目标程序集上设置 InternalsVisibleTo 属性,以允许从临时程序集访问其内部成员;否则,模拟对象无法覆盖内部成员,因为它无权访问它(这也是模拟方法必须标记为虚拟的原因)。请注意,即使单元测试和被测试的类在同一个程序集中也是如此。

    因此,您需要确保目标类的程序集使其内部对代理程序集可见(例如在 AssemblyInfo.cs 中):

    【讨论】:

    • 刚刚花了几个小时试图弄清楚我错过了什么。迟到总比不到好。感谢您提供信息。
    【解决方案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")]
    

    添加您需要的任何程序集,瞧(我不得不放置多个程序集)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      • 2011-09-20
      • 2011-08-08
      • 2011-04-01
      • 2011-09-05
      相关资源
      最近更新 更多