C# 无法使用Rhino Mock为内部类型创建模拟类

C# 无法使用Rhino Mock为内部类型创建模拟类,c#,unit-testing,rhino-mocks,internal,internalsvisibleto,C#,Unit Testing,Rhino Mocks,Internal,Internalsvisibleto,我使用Rhino Mock作为单元测试的模拟框架 我有一个名为Subject的类,这是我想要测试的类。它依赖于IStore IStore的定义如下: //internal interface : has InternalsVisible to both "Subject" //and "StoreTests" class namespaces internal interface IStore { void Store(string name); //other methods

我使用Rhino Mock作为单元测试的模拟框架

我有一个名为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
}
//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 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
}
//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
}
我使用Rhinomock的测试类如下所示:

//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
}
//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
}
//测试类
类存储测试{
主题=新主题();
[测试]
公共存储测试(){
//安排
var mockStore=MockRepository.GenerateMock();
字符串testName=“test”;
Expect(x=>x.Store(testName)).Returns(null);
//表演
subject.Store(testName);
//断言
mockStore.verifyallexpections();
}
//其他试验方法
}
在我的设置中,接口被定义为internal,它为Subject类和StoreTests类都设置了InternalsVisible。但是,当测试用例执行时,它会在var mockStore=MockRepository.GenerateMock()处抛出一个异常; 说IStore不是公共的,因此无法生成模拟

我想这是因为史实不是公开的。但是,由于我已经在IStore dll上设置了InternalsVisibleTo,StoreTests为该类创建一个模拟是否就足够了


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

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

[程序集:InternalsVisibleTo(“Tests.assembly.Name”)]
[大会:InternalsVisibleTo(“NUnit.Framework”)]
[组装:内部可视(“Rhino.Mocks,公钥=0024000000480000094000000060200000002400005253413100040000010001009D1CF4B75B7218B141AC64C15450141B1E5F41F46A302AC717AB9761FA6AE20C354C22D0A60AC59DE41FA285D572E7CF33C320AA7FF877E2B7DA1792FC6AA4EB0B4D8294A2F74CB14D03FB9B091F756DC49E626D74601692C998BE777ED767E40C36CF337B677E67676ECC4647AD646AB”)]
[组件:内部可视到(”动态加氧组件2,公钥=002400048000009400000006020000000240000525341310004000001000100C547CAC37ABD99C8DB225EF2F6C8A3602F3B3606CC9891605D02BAA56104F4CFC0734AA39B93BF7852F7D9266654753CC297E7EDFe0Bac1CDCF9F714150E0A7B191195B7667BB4F64B8E2380FD1D9D46AD92D2D9D92D1560934CEAF414141417F7045cc7“]

您是否尝试让Rhino Mock可以看到组件内部

[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]
有关详细信息,请参阅

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

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


好吧,这可能会得到回答,但对我来说它不起作用

以下是我所做的工作(可能会在下一个项目中帮助他人,甚至是我):

在Visual studio的工具菜单中: 外部工具: 加上我写的名字“Longstrogname”,但放上你觉得合适的:

(此路径或sn.exe为您提供的任何位置):

命令:
C:\Program Files\Microsoft SDK\Windows\v6.0A\Bin\sn.exe
论据:
-Tp$(目标路径)
(单击复选框,输出到“使用输出窗口”)

现在,您可以单击项目,然后转到“工具”并转到“LongStrongName”菜单:

VS将输出:

公钥是02400000480000094000000060200000002400005253413100040000010000001009BADBE86C32EC0
ec429f0b3909*********
公钥令牌是6ccc051********
打开assembly.cs并添加:

[程序集:内部可视到("动态加氧组件2,公钥=002400048000009400000006020000000240000525341310004000001000100C547CAC37ABD99C8DB225EF2F6C8A3602F3B3606CC9891605D02BAA56104F4CFC0734AA39B93BF7852F7D9266654753CC297E7EDFe0Bac1CDCF9F714150E0A7B191195B7667BB4F64B8E2380FD1D9D46AD92D2D9D92D1560934CEAF414141417F7045cc7“]

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

这个答案也很好。将另一个标记为已接受,因为它提供了指向wiki中其他信息的链接。只花了几个小时试图找出我缺少的内容。迟做总比不做好。感谢您提供的信息。