Невозможно создать класс Mock для внутреннего типа, используя Rhino Mocks - PullRequest
18 голосов
/ 28 июля 2011

Я использую 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
}

В моей настройке интерфейс определен как внутренний, и для него установлен InternalsVisible как для класса Subject, так и для класса StoreTests.Однако, когда тестовый пример выполняется, он выдает исключение в var mockStore = MockRepository.GenerateMock ();говоря, что IStore не является публичным и, следовательно, он не может генерировать макет.

Я думаю, это потому, что IStore не является публичным.Однако, поскольку я установил InternalsVisibleTo в dll IStore, не будет ли для StoreTests недостаточно создать макет для этого класса?

Теперь я думаю, что эту проблему можно решить, сделав интерфейс IStore общедоступным.Однако, учитывая, что это не вариант для меня, есть ли другой способ создать макет для IStore?

Ответы [ 3 ]

34 голосов
/ 28 июля 2011

Вы пытались сделать внутренние компоненты сборки видимыми для насмешек Rhino?

[assembly: InternalsVisibleTo ("DynamicProxyGenAssembly2")]

Подробнее см. Внутренние члены Rhino Mocks .

Когда класс подвергается моделированию, во время выполнения генерируется новый класс, производный от проверяемого класса. Этот сгенерированный класс находится в отдельной «временной» сборке, которая называется «DynamicProxyGenAssembly2». Итак, атрибут InternalsVisibleTo должен быть установлен на целевой сборке, чтобы разрешить доступ к ее внутренним элементам из временной сборки; в противном случае фиктивный объект не может переопределить внутренний элемент, так как он не имеет к нему доступа (именно поэтому макетный метод должен быть помечен как виртуальный). Обратите внимание, что это верно, даже если модульный тест и тестируемый класс находятся в одной сборке.

Итак, вам нужно убедиться, что сборка целевого класса делает его внутренние компоненты видимыми для сборки прокси как таковой (например, в AssemblyInfo.cs):

10 голосов
/ 28 июля 2011

Да, этого должно быть достаточно, чтобы добавить в файл AssemblyInfo.cs проверяемой сборки:

[assembly: InternalsVisibleTo("Tests.Assembly.Name")]
[assembly: InternalsVisibleTo("NUnit.Framework")]
[assembly: InternalsVisibleTo("Rhino.Mocks, PublicKey=00240000048000009400000006020000002400005253413100040000010001009D1CF4B75B7218B141AC64C15450141B1E5F41F6A302AC717AB9761FA6AE2C3EE0C354C22D0A60AC59DE41FA285D572E7CF33C320AA7FF877E2B7DA1792FCC6AA4EB0B4D8294A2F74CB14D03FB9B091F751D6DC49E626D74601692C99EAB7718ED76A40C36D39AF842BE378B677E6E4EAE973F643D7065241AD86ECC156D81AB")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
3 голосов
/ 03 августа 2012

Ну, на это можно ответить, но для меня это не сработало.

Итак, вот что я сделал, чтобы заставить его работать (может помочь другим, и даже мне, в следующем проекте ....):

В меню «Инструменты» в 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")]

добавьте все необходимые вам сборки и вуаля (мне пришлось поставить несколько сборок).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...