Я думаю, что модульное тестирование этого класса будет довольно простым, если мы просто внесем пару небольших изменений. Прежде всего вы наверняка хотели бы избавиться от следующего:
Timer echoReceived = new Timer(200ms);
Ожидание 200 мс в каждом модульном тесте не является хорошей идеей. Вместо этого вы можете извлечь эти 200 мс в поле класса, инициализированное из конструктора, чтобы вы могли передать ему более низкие значения, например, 1 мс. Но на самом деле вы могли бы сделать это еще лучше, определив интерфейс, такой как ITimer, который мог бы выглядеть примерно так:
interface ITimer
{
int Interval { get; }
event EventHandler OnElapsed;
void Reset();
}
Таким образом, в модульном тесте вы можете указать заглушку, например реализовано так
class StubTimer
{
[...]
void TickNow()
{
OnElapsed.Invoke( ... ) // fire the event, to avoid Thread.Sleep (waiting n miliseconds)
}
[...]
}
Вероятно, вы должны также взять функцию ShowError
в качестве параметра конструктора, присвоив его свойству типа, подобного Action<ErrorArgs>
. Затем вы можете просто протестировать его следующим образом:
public void WhenClientConnected_ButThereIsNoResponse_ItShouldCallShowError()
{
var stubHearbeatTimer = new StubTimer();
var stubTimeoutTimer = new StubTimer();
// i'm pretty sure it's possibile mock Actions with moq as well
var wasSendErrorCalled = false;
var stubErrorAction = (args) => {
wasSendErrorCalled = true;
};
var sut = new connector(stubHearbeatTimer, stubTimeoutTimer, stubErrorAction );
sut.OnClientConnected( ..dummyClient..);
stubTimeoutTimer.TickNow();
Assert.IsTrue(wasSendErrorCalled);
}
Обратите внимание, что это просто псевдокод. Надеюсь, что это отвечает на ваш вопрос!