Модульное тестирование многопоточной среды с точками останова в Visual Studio 2008 - PullRequest
1 голос
/ 18 февраля 2011

У меня проблема при отладке юнит-теста в Visual Studio 2008. Юнит-тест использует System.Timers.Timer (в рамках бизнес-логики) для обработки определенной задержки (1000 мс). Поток, на котором выполняется тестирование, помещается в спящий режим на 5 000 миллисекунд.

При самостоятельном запуске теста он проходит. При запуске всех тестов (> 120) оно иногда проходит, а иногда и не проходит ( не детерминировано ). Затем я попытался установить точку останова в фиктивном объекте, где я установил флаг, который устанавливается в модульном тесте. Теперь, когда я отлаживаю тест самостоятельно, я получаю явление, что Assert.IsTrue() терпит неудачу, но Quick Watch говорит мне, что это правда:

Assert.IsTrue(true) fails: why?

public class ObjectManagerAccessMock : IObjectManagerAccess
{
    public bool ExecuteCommandWasCalled { get; set; }

    public void ExecuteCommand()
    {
        ExecuteCommandWasCalled = true; //set breakpoint here
    }
}

Продолжает ли поток, выполняющий тест, после остановки другого потока (через точку останова)?

Ответы [ 2 ]

1 голос
/ 18 февраля 2011

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

Увеличение времени ожидания в вашем тесте должно решить проблему, но будьте осторожны.

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

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

[Test]
public void DemonstrateThatTheTestRunsAsFastAsTheSubjectUnderTest()
{
     var resetEvent = new ManualResetEvent(true);

     // configure our test to listen for the completed event
     var subject = new MyTestSubject();
     subject.OnComplete += (sender,e) => resetEvent.Set();

     // perform the long running asynchronous operation
     subject.DoLongRunningOperation();

     // wait up to 10 seconds
     resetEvent.WaitOne(100000);

     Assert.AreTrue(subject.OperationComplete);
}

В приведенном выше примере мы используем ManualResetEvent , который будет блокировать выполнение до вызова операции Set . Также обратите внимание, что я передаю значение таймаута для события сброса, чтобы операция не выполнялась вечно. Если тайм-аут превышен, вполне вероятно, что наш OperationComplete все равно будет ложным, поэтому тест не пройден.

Если вы хотите, чтобы более мелкие детали определяли, истекло ли время ожидания теста, метод WaitOne возвращает логическое значение, указывающее, была ли операция успешной.

bool completedWithoutTimeout = resetEvent.WaitOne(10000);
Assert.IsTrue(completedWithoutTimeout, "The operation timed out.");
0 голосов
/ 18 февраля 2011

Может быть, иногда ваш BL занимает более 4 секунд, поэтому он складывается в более чем 5 секунд, и утверждение не удается, но к тому времени, когда вы можете проверить его с помощью Quick Watch, операция завершена, и вызов устанавливает значение true.

Я уверен, что 1) утверждение не выполнено, потому что значение является ложным во время утверждения 2) значение является истинным к тому моменту, когда вы его проверяете, и времени между этими двумя действиями> 0

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