UnitTesting многопоточного класса, избегая Thread.Sleep () в тесте?

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

public class FileGroupGarbageCollector
{
    private Task _task;

    private readonly AutoResetEvent _event = new AutoResetEvent(false);

    public void Start()
    {
        _task = Task.Factory.StartNew(StartCollecting);

    }

    public void Stop()
    {
        _event.Set();
    }

    private void StartCollecting()
    {
        do
        {
            Process();
        }
        while (!_event.WaitOne(60000, false));            
    }

    private void Process()
    {
        /* do some work to the database and file system */
    }
}

Это не должен быть самый хорошо сформированный класс, просто пытаюсь выяснить что-нибудь!

Затем у меня есть модульный тест, в котором я хочу запустить, а затем остановить службу, утверждая, что частный метод 'Processs' что-то сделал с базой данных или файловой системой.

Мой модульный тест выглядит следующим образом ( nunit):

    [Test]
    public void TestStart()
    {
        var fg = new FileGroupGarbageCollector(30000);

        fg.Start();

        Thread.Sleep(5000); // i hate this!

        fg.Stop();

        // assert it did what i wanted it to do!
    }

Есть ли какой-нибудь способ или какой-нибудь хороший шаблон, который можно использовать здесь, чтобы избежать использования Thread.Sleep ()? Мне не нравится идея спать в модульном тесте (не говоря уже о производственном коде), но я отказываюсь просто тестировать частные функции! Я хочу протестировать общедоступный интерфейс этого класса.

Любые ответы приветствуются :)

ОБНОВЛЕНИЕ ПОСЛЕ ОТВЕТА

Я выбрал способ IoC, и он отлично работает :)

открытый интерфейс IEventFactory { IEvent Create (); }

public interface IEvent
{
    bool WaitOne(int timeout);
    void Set();
}

Затем мои имитирующие объекты (с использованием Moq):

 var mockEvent = new Mock<IEvent>();
 var mockEventFactory = new Mock<IEventFactory>();

 mockEvent.Setup(x => x.WaitOne(It.IsAny<int>())).Returns(true);
 mockEvent.Setup(x => x.Set());

 mockEventFactory.Setup(x => x.Create()).Returns(mockEvent.Object);

Итак, мгновенно вызов IEvent.WaitOne () возвращает true и завершается, поэтому нет необходимости в Thread.Sleep ()!

:)

5
задан adamwtiko 8 July 2011 в 18:45
поделиться