不能使用Rhino Mock为内部类型创建Mock类

本文关键字:Mock 类型 创建 内部 Rhino 不能 | 更新日期: 2023-09-27 18:03:52

我使用Rhino Mocks作为单元测试的mock框架。

我有一个名为Subject的类,这是我想测试的类。它依赖于store。

store定义如下:

//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。

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

现在我认为这个问题可以通过使IStore接口公开来解决。然而,考虑到这不是我的选择,是否有其他方法可以为IStore创建模拟?

不能使用Rhino Mock为内部类型创建Mock类

您是否尝试使程序集内部对Rhino mock可见?

[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]

参见Rhino模拟内部成员。

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

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

在测试下的程序集的AssemblyInfo.cs文件中添加以下内容应该足够了:

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

这可能是答案,但对我来说它不起作用。

所以这是我所做的使它工作(可能帮助别人,甚至我,在下一个项目....):

在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")]

添加您需要的任何程序集,然后瞧(我必须放置多个程序集)。