Как выполнить модульное тестирование нескольких зависимостей - PullRequest
0 голосов
/ 30 сентября 2019

Я хотел бы написать некоторые модульные тесты на C # (используя NUnit), но я не уверен, как продолжить.

Итак, у меня есть класс, который представляет пользовательскую модель DataModel с четырьмя свойствами. Я отправляю эту модель в свой конструктор ExcelInit.

DataModel dm = new DataModel();
dm.PopulateDataModel(holder);

ExcelInit d1 = new ExcelInit(dm);
d1.BeginProcess();

, а затем в BeginProcess запускаю свой фактический метод.

public class ExcelInit
{
    public DataModel _model { get; set; }

    public ExcelInit(DataModel model)
    {
        _model = model;
    }

    public void BeginProcess()
    {
        DataReader dr = new DataReader();
        CellLocation cl = new CellLocation();
        //Gets the corresponding cellAddress for the cell that contains "2x5" from our hidden config-sheet
        var correspondingCellsAddress = cl.FindCorrespondingCellAddress(_model.boxSize);
        //returns the range that we need to copy i.e. the whole range of the box ala B3:AG13
        var srcRange = dr.GetRangeForSourceDestination(correspondingCellsAddress);
        //Last row of sheet 6 (the sheet we populate) with input-boxes
        var lastRow = dr.FindLastRowByName("Your_Data_Sheet") + 3;
        //gets the cell we'll copy our range to
        var destRange = "B" + lastRow.ToString();

        DataHandler dh = new DataHandler();
        dh.CopyBox(srcRange, destRange, _model);
    }

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

Ответы [ 2 ]

1 голос
/ 30 сентября 2019

Цель DI - не избегать создания экземпляров. Даже DI-контейнер должен каким-то образом создавать экземпляры ваших зависимостей, например, с помощью отражения.

Вместо этого DI составляет примерно , где для создания этих экземпляров. Сказав это, вы не должны позволять вашей тестируемой системе (SuT, в вашем случае класс ExcelInit) создавать свои собственные зависимости, а просто вводить их в систему, например, с помощью инжектора-конструктора или простодобавив в метод paremeter:

public void BeginProcess(DataReader dr, CellLocation cl, DataHandler dh)
{
    //Gets the corresponding cellAddress for the cell that contains "2x5" from our hidden config-sheet
    var correspondingCellsAddress = cl.FindCorrespondingCellAddress(_model.boxSize);
    //returns the range that we need to copy i.e. the whole range of the box ala B3:AG13
    var srcRange = dr.GetRangeForSourceDestination(correspondingCellsAddress);
    //Last row of sheet 6 (the sheet we populate) with input-boxes
    var lastRow = dr.FindLastRowByName("Your_Data_Sheet") + 3;
    //gets the cell we'll copy our range to
    var destRange = "B" + lastRow.ToString();

    dh.CopyBox(srcRange, destRange, _model);
}

Теперь в вашем тесте у вас есть это:

var target = new ExcelInit();
target.BeginProcess(new DataReader(), new CellLocation(), new DataHandler());

Конечно, это выполнит точно такие же инструкции. Однако теперь вы также можете сделать это:

var target = new ExcelInit();
target.BeginProcess(new SomeSpecificDataReader(), new CellLocation(), new DataHandler());

Поскольку вы просто вводите читатель вместо того, чтобы создавать его в своем SuT, ваш фактический SuT вообще не меняется. Таким образом, на самом деле тестируемая система не зависит от конкретного файла , а вместо этого зависит от данных . Где хранятся эти данные, не должно иметь никакого значения для вашего BeginProcess -метода. Например, вы можете предоставить другой файл Excel (при условии, что ваша система использует файлы Excel), файл XML или даже какое-то хранилище данных в памяти.

0 голосов
/ 30 сентября 2019

Ваш учитель, кажется, вводит вас в заблуждение и, возможно, вводит в заблуждение самого себя.

Его предложение сработает, если вы зависите от зависимости. Это не ваш случай. Вы используете API-интерфейс Excel напрямую и добавление классов, которые вы создаете с помощью new, не поможет вам с тестируемостью. Если бы вы следовали совету своего учителя, вам пришлось бы создавать тестовые дубли для всего API Excel, что, я полагаю, невозможно, поскольку этот API не предназначен для тестируемости.

Один из способов следовать совету вашего учителябыло бы создать свой собственный API, который обертывает тот из Excel. Это может быть сделано с учетом тестируемости. Но, глядя на ваш код, я чувствую, что это всего лишь подтолкнет проблему на один уровень вниз. Вы бы усложнили свое решение, не имея автоматических тестов для кода, который действительно имеет значение.

Я бы порекомендовал попросить вашего учителя привести пример того, что он имеет в виду. И как внедрение этих классов улучшит тестируемость кода, написав реальный тест. Я уверен, что он тоже поймет свое предложение, если не поможет в создании более тестируемого кода в вашем сценарии.

...