2011-07-28 54 views
15

我正在使用Rhino Mocks作为单元测试的嘲讽框架。无法使用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 
} 

和主题类被定义为如下:

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类和Sto设置的InternalsVisible重新测试课程。但是,当测试用例执行时,它会在var mockStore = MockRepository.GenerateMock();时引发异常。 表示IStore不公开,因此无法生成模拟。

我认为这是因为IStore不公开。但是,由于我已经在IStore dll上设置了InternalsVisibleTo,它会不足以让StoreTests为该类创建一个模拟?

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

回答

27

你尝试使装配内部可见犀牛嘲笑?

[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")] 

有关详细信息,请参阅Rhino Mocks Internal Members

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

所以,你需要确保目标类的组件使得其内部的代理组件可见这样(在AssemblyInfo.cs中为例):

+1

感谢您的链接!它现在有效。 – Santhosh

10

是的,应该足以补充以下的的AssemblyInfo.cs文件组件的测试下:

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

这个答案也很好。将其他标记为已接受,仅仅是因为它提供了wiki中其他信息的链接。 – Santhosh

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

添加你需要的任何组件,瞧(我不得不把多个程序集)。

相关问题