Не могу выполнить модульное тестирование метода, который вызывает статический метод, как я могу перепроектировать эту программу? - PullRequest
0 голосов
/ 26 июня 2018

У меня есть класс, который записывает журналы в текстовый файл по всей программе. Я подумал, что было бы неплохо создать методы static, так как он имеет только несколько методов и вызывается во многих различных частях программы. Этот метод вызывается один раз при запуске программы для создания исходного файла.

public static void CreateAuditLog()
{
    var fileName = Path.Combine(filePath, 
        $@"AuditFile{DateTime.Now:yyyy-MM-dd_hh-mm-ss-fff}.txt");

    writer = new StreamWriter(new FileStream(fileName,
        FileMode.CreateNew, FileAccess.Write));

    GetAuditLogFileSize();
}

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

public Decimal CalculateCurrentBalance
{
    get
    {
        var balance = TotalAmountBilled - TotalAmountPaid;
        Audit.Message(2, $"Balance: {balance} for: {Name}");
        return TotalAmountBilled - TotalAmountPaid;
    }
}

метод сообщения имеет много деталей, поэтому я не буду публиковать здесь все, но в основном он требует числа и сообщения для записи в текстовый файл. Модуль записи потока специально оставлен открытым в CreateAuditLog(), чтобы Message() можно было вызывать во многих разных местах, а сообщения записывались в файл журнала.

public static void Message(int auditLevel, string message)

Мне кажется, что я плохо спроектировал эту программу. Кто-нибудь есть какие-либо предложения о том, как я могу изменить дизайн? Я не уверен, как я могу сделать это, не создавая экземпляр моего класса журналирования на каждом другом классе в программе.

1 Ответ

0 голосов
/ 26 июня 2018

Не создавать экземпляр в любом другом классе; ввод один.

Это одна из основ модульного тестирования; Внедрение зависимости. Классы не создают и не получают прямого доступа к своим зависимостям, им передается тот, который используется. В этом случае, если ваш Log класс реализует ILogger (интерфейс, который вы создаете), тогда ваш класс будет выглядеть так:

public class MyInjectedClass
{
     private readonly ILogger logger;
     public MyInjectedClass(ILogger logger)
     {
        this.logger = logger;
     }

     public void SomeMethod()
     {
        logger.Message();
     }
}

Конечно, теперь вы должны передать экземпляр ILogger повсюду, и это большая проблема. К счастью, есть много библиотек, таких как NInject и Autofac, которые подключат все зависимости для вас. Это потребует некоторого рефакторинга, но как только вы закончите, вы просто зарегистрируете свой класс журналирования как одноэлементный для интерфейса ILogger, и он будет автоматически внедрен в каждый класс, который имеет его как зависимость.

(MS также имеет библиотеку DI, включенную в .NET Core, если вы ее используете)

Интерфейс может выглядеть примерно так:

public interface ILogger
{
     void Message(string msg);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...