Избегание thread.sleep в коде при модульном тестировании с Moq - PullRequest
0 голосов
/ 13 марта 2019

У меня есть методы с несколькими thread.sleep, которые длятся по 20 секунд. Это бизнес-требование. Я пытаюсь провести модульное тестирование этих методов, высмеивая и пропуская эти сны, чтобы тесты могли работать быстрее и фактически не ждать 20 секунд. Использование фреймворка moq. Ценю любые идеи о том, как это реализовать.

Ответы [ 3 ]

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

Вероятно, нет способа смоделировать Thread.Sleep, потому что это статический метод, и он не может быть смоделирован с помощью основанных на DynamicProxy фреймворков, таких как moq.

Один из вариантов - использовать инструменты на основе Profiler API, например Microsoft Fakes (только в VS Enterprise) или Typemoq professional.

Лучший вариант - не вызывать Thread.Sleep непосредственно в вашей бизнес-логике. Вместо этого вы можете ввести такой интерфейс

public interface ISleepService
{
    void Sleep(int ms);
}

Затем создайте реализацию по умолчанию, которую вы используете в своем коде:

public class SleepService: ISleepService
{
    public void Sleep(int ms)
    {
       Thread.Sleep(ms);
    }
}

Добавление зависимости ISleepService в вашу бизнес-логику

public class MyBusinessLogic()
{
    private ISleepService _sleepService;
    public MyBusinessLogic(ISleepService sleepService)
    {
        _sleepService = sleepSerivce;
    }

    public void MyBusinessMethod()
    {
        // your code
        _sleeService.Sleep(20000);
        // more code
    }
}

Затем вы можете легко смоделировать ISleepService в своих модульных тестах и ​​передать реальную реализацию в свой производственный код

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

На самом деле вы можете ввести интерфейс для методов Thread.sleep, и вы можете поиздеваться над ним при написании UT

 public interface IThreadSleep
{
    void Sleep(int milliSec);

}

Вы можете иметь реализацию, что-то вроде этого

 public class ThreadSleep : IThreadSleep
{
    public void Sleep(int milliSec)
    {
        Thread.Sleep(milliSec);
    }
}

В вашем бизнес-классе просто внедрите этот интерфейс, и затем вы можете смоделировать Thread.sleep

 public class Class1
{
    IThreadSleep _threadSleep;
    public Class1(IThreadSleep threadSleep)
    {
        _threadSleep = threadSleep;

    }

    public void SomeMethod()
    {
        // 
        _threadSleep.Sleep(100);
    }
}

Надеюсь, это поможет.

0 голосов
/ 13 марта 2019

Не знаю, какой у вас настоящий код, но, по крайней мере, чтобы иметь представление.Вы можете обернуть ваш Thread.Sleep в interface и затем вставить его в ваш бизнес-обработчик \ контроллер.В реальной реализации используйте Thread.Sleep для фактического ожидания, но в тестах имитируйте, что interface, чтобы избежать Thread.Sleep.Например:

public interface IMySleepContext
{
    void Sleep(int milliseconds);
}

public class MySleepContext : IMySleepContext
{
    public void Sleep(int milliseconds)
    {
        Thread.Sleep(milliseconds);
    }
}

public class MyController
{
    private readonly IMySleepContext _mySleepContext;

    public MyController(IMySleepContext mySleepContext)
    {
        _mySleepContext = mySleepContext;
    }

    public void MyMethod()
    {
        //do something
        _mySleepContext.Sleep(20000);
        //do somethign
    }
}

Тесты:

//Arrange
MyController mc = new MyController(Mock.Of<IMySleepContext>());

//Act
mc.MyMethod();

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