Написание модульных тестов для класса, который запускает внешний EXE

9

Я написал класс C #, который используется для запуска списка EXE-файлов (не одного из моих - сторонних EXE-файлов, которые я должен запускать) и поддерживаю их работу (периодически проверяю, чтобы убедиться, что они все еще работают, и запускаю их, если нет) ,

Я могу проверить основную логику добавления, удаления и т. Д. В порядке. Как выполнить модульное тестирование, чтобы действительная работа по сохранению EXE-файлов работала?

Моя первоначальная мысль - запустить фиктивный EXE-файл, который закрывается через 1 секунду, а затем использовать его для тестирования. Это выходит за рамки модульного тестирования?

MattW
источник

Ответы:

12

Моя первоначальная мысль - запустить фиктивный EXE-файл, который закрывается через 1 секунду, а затем использовать его для тестирования. Это выходит за рамки модульного тестирования?

Это хороший тест? Конечно, так что создайте это. Является ли это «модульным тестом» в реальном смысле этого слова? Я так не думаю, я бы назвал это «системным тестом» или чем-то в этом роде, но это не делает тест менее ценным.

Док Браун
источник
9

Макет на более высоком уровне, чем это. Создайте прокси-класс Process.Start(), подделайте его в тесте и проверьте входные данные.

public interface IProcessProxy
{
     ProcessInfo Start(string application, string[] arguments);
}

public class ProcessProxy : IProcessProxy
{
    public ProcessInfo Start(string application, string[] arguments)
    {
        return Process.Start(application, arguments);
    }
}

// You could use a mocking framework for this, but for the purposes
// of this example ...
public class FakeProcessProxy : IProcessProxy
{
    private string _expectedApplication;
    private string[] _expectedArguments;
    private ProcessInfo response;

    public FakeProxy(string expectedApplication, string[] expectedArguments, ProcessInfo response)
    {
         _expectedApplication = expectedApplication;
         _expectedArguments = expectedArguments;
    }

    public ProcessInfo Start(string application, string[] arguments)
    {
         // compare input to expectations and throw exception if not matching
         return _response;
    }
}

// You can also use an IoC framework to inject your IProcessProxy, but I won't.
public class ClassUnderTest
{
    public ClassUnderTest(IProcessProxy proxy)
    {
        _proxy = proxy;
    }

    public ClassUnderTest() : this(new ProcessProxy())
    {
    }

    public void MethodUnderTest()
    {
        // Do stuff

        ProcessInfo process = _proxy.Start(@"C:\Program Files\App\App.exe", new[] { "arg1", "arg2" });
        process.WaitForExit();

        if (process.ExitCode == 0)
        {
            // Act on success
        }
        else
        {
            // Act on failure
        }
    }   
}

Везде, где вам нужно использовать ClassUnderTest в коде приложения, используйте конструктор по умолчанию. В своих тестах передайте FakeProcessProxy другому конструктору, используя ожидаемые параметры запуска Proxy и результаты теста в конструкторе fake.

прецизионный самописец
источник
4

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

Но с прагматической точки зрения ваш подход хорош, хотя 1 секунда кажется немного длинной.

keppla
источник
1

Я сделал что-то подобное, но только что позвонил ping localhost. Избавляет от необходимости размещать исполняемые файлы на вашем сервере сборки

Бен
источник