Правильное использование внутреннего класса при тестировании с базовым базовым тестовым классом - PullRequest
0 голосов
/ 22 марта 2019

TL; DR Я не могу заставить InternalsVisibleTo работать с моими юнит-тестами

Фон

В настоящее время я разрабатываю библиотеку, в которой я хотел бы сделать некоторые (но не все) классы внутренними, чтобы не запутать пользователей. Только некоторые из классов должны быть публичными из этой библиотеки.

Я подумал, что это будет хороший проект, чтобы узнать, как работать с внутренним ключевым словом в C #.

Всякий раз, когда я делаю новый проект, я обнаруживаю, что использую вариант DDD, в котором я делю обязанности на разные DLL, но ради этого вопроса, подумайте о структуре моего проекта следующим образом (сверху вниз ):

  • Исполняемый файл, использующий мою библиотеку
  • Библиотека, которую я разрабатываю
  • Библиотека модульного тестирования для модульного тестирования моей библиотеки
  • Библиотека инструментов тестирования, содержащая базовый класс для всех модульных тестов

Рабочий пример архитектуры вы можете посмотреть на мой проект HelloWorld на github. Этот пример не повторяет проблему здесь, он только иллюстрирует, как я обычно делаю слой на свой код.

Я часто создаю базовый класс для своих модульных тестов, который создает макеты для любого типа, который я тестирую, то есть этот пример:

public class TestsFor<TInstance> where TInstance : class
{
    protected MoqAutoMocker<TInstance> AutoMock { get; set; }
    protected TInstance Instance { get; set; }

    public TestsFor()
    {
        AutoMock = new MoqAutoMocker<TInstance>();

        RunBeforeEachUnitTest(); // virtual

        Instance = AutoMock.ClassUnderTest;

        RunAfterEachUnitTest(); // virtual
    }
}

Проблема

Юнит-тесты, которые я пишу, часто принимают их в виде:

public class ReportServiceTests : TestsFor<ReportService>
{
    [Fact]
    public async Task CreateReport_WhenCalled_LogsTheCall()
    {
        // Act
        await Instance.CreateReport();

        // Assert            
        GetMockFor<ILogger>().Verify(logger => logger.Enter(Instance, nameof(Instance.CreateReport)), Times.Once());
    }
}

Где каждый модульный тест будет выводить класс TestsFor для того, чтобы дать мне готовый класс для имитации теста. Тем не менее, хотя я пометил свои внутренние классы InternalsVisibleTo , указывая их как на сборку юнит-теста, так и на сборку инструментов тестирования (где находится базовый класс юнит-теста), я ВСЕ ЕЩЕ получаю Непоследовательная доступность Ошибки.

Кто-нибудь знает, как это обойти?

1 Ответ

1 голос
/ 24 марта 2019

Проблема, с которой вы сталкиваетесь, заключается в том, что вы пытаетесь создать класс, более доступный, чем его базовый класс.

Вы можете делегировать вместо получения:

public class ReportServiceTests
{
    private Tests tests = new Tests();

    [Fact]
    public async Task CreateReport_WhenCalled_LogsTheCall()
    {
        tests.CreateReport_WhenCalled_LogsTheCall();
    }

    private class Tests : TestsFor<ReportService>
    {
        public async Task CreateReport_WhenCalled_LogsTheCall()
        {
            // Act
            await Instance.CreateReport();

            // Assert            
            GetMockFor<ILogger>().Verify(logger => logger.Enter(Instance, nameof(Instance.CreateReport)), Times.Once());
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...