我使用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不公开,因此无法生成模拟。
我认为这是因为IStore不公开。但是,由于我在IStore dll上设置了InternalsVisibleTo,StoreTests是否足以为该类创建模拟?
现在我认为可以通过公开IStore接口来解决这个问题。但是鉴于这不是我的选择,我还能为IStore创建一个模拟器吗?
答案 0 :(得分:34)
您是否尝试过使用Rhino嘲讽可以看到装配体的内部构件?
[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]
有关详细信息,请参阅Rhino Mocks Internal Members。
当一个类被模拟时,会在运行时生成一个新类,该类派生自模拟类。这个生成的类驻留在一个单独的“临时”程序集中,该程序集称为“DynamicProxyGenAssembly2”。因此,需要在目标程序集上设置InternalsVisibleTo属性,以允许从临时程序集访问其内部成员;否则,模拟对象不能覆盖内部成员,因为它无法访问它(这也是为什么模拟方法必须标记为虚拟)。请注意,即使单元测试和测试类在同一个程序集中也是如此。
因此,您需要确保目标类的程序集使其内部对代理程序集可见(例如,在AssemblyInfo.cs中):
答案 1 :(得分:10)
是的,它应该足以在测试下的程序集的 AssemblyInfo.cs 文件中添加以下内容:
[assembly: InternalsVisibleTo("Tests.Assembly.Name")]
[assembly: InternalsVisibleTo("NUnit.Framework")]
[assembly: InternalsVisibleTo("Rhino.Mocks, PublicKey=00240000048000009400000006020000002400005253413100040000010001009D1CF4B75B7218B141AC64C15450141B1E5F41F6A302AC717AB9761FA6AE2C3EE0C354C22D0A60AC59DE41FA285D572E7CF33C320AA7FF877E2B7DA1792FCC6AA4EB0B4D8294A2F74CB14D03FB9B091F751D6DC49E626D74601692C99EAB7718ED76A40C36D39AF842BE378B677E6E4EAE973F643D7065241AD86ECC156D81AB")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
答案 2 :(得分: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")]
添加你需要的任何组件,瞧(我必须放置多个组件)。