Как мне протестировать событие, вызванное тестируемым классом? - PullRequest
1 голос
/ 21 октября 2019

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

public class EventRaiserClass : IEventRaiserClass 
{
    public event EventHandler SendEventToClient;

    public void RaiseEventForClient()
    {
        SendEventToClient?.Invoke(this, EventArgs.Empty);
    }
}

Вот мой класс клиента

public class Client :IClient
{
    EventRaiserClass _eventRaiser;
    public Client(EventRaiserClass eventraiser)
    {
        _eventRaise = eventraise;
        _iotGwStatus.SendEventToClient += OnSendEventToClient;
    }

    private async void OnSendEventToClient(object sender, EventArgs e)
    {
        await SendEventToClient();
    }

    public async Task SendEventToClient()
    {
        //do some operation
    }
}

EventRaiserClass вводится нижекласс, который отвечает за обработку некоторых заказов

public class ProcessRequest: IProcessRequest
{
    IEventRaiserClass _evntRaiser;
    public ProcessRequest(IEventRaiserClass evntRaiser)
    {
        _evntRaiser = evntRaiser;
    }

    public void Process(JObject json)
    {
        _evntRaiser.RaiseEventForClient(); 
    }
}

Теперь, как мне выполнить юнит-тестирование по методу Process? Как убедиться, что событие вызывается при вызове метода process?

Ответы [ 2 ]

7 голосов
/ 21 октября 2019

Насколько я могу судить, класс Client не имеет отношения к этому вопросу? Вы просто хотите проверить звонки ProcessRequest.Process звонки EventRaiserClass.RaiseEventForClient.

Простой способ, без каких-либо насмешек, используя EventRaiserClass:

var eventRaiser = new EventRaiserClass();
bool eventRaised = false;
eventRaiser.SendEventToClient += (o, e) => eventRaised = true;

var processRequest = new ProcessRequest(eventRaiser);
processRequest.Process(someJObject);

Assert.True(eventRaised);

Вы можете пойти дальше, ипроверьте, что событие вызывается ровно один раз:

// Arrange
var eventRaiser = new EventRaiserClass();
int eventRaisedCount = 0;
eventRaiser.SendEventToClient += (o, e) => eventRaisedCount++;

var processRequest = new ProcessRequest(eventRaiser);

// Act
processRequest.Process(someJObject);

// Assert
Assert.Equal(1, eventRaisedCount);

Если вы не хотите полагаться на EventRaiserClass и используете фальшивый фреймворк, вы можете сделать что-то подобное (я использую Moq в этом примере):

// Arrange
var eventRaiser = Mock<IEventRaiser>();
var processRequest = new ProcessRequest(eventRaiser.Object);

// Act
processRequest.Process(someJObject);

// Assert
eventRaiser.Verify(x => x.RaiseEventForClient());

То же самое с использованием NSubstitute :

// Arrange
var eventRaiser = Substitute.For<IEventRaiser>();
var processRequest = new ProcessRequest(eventRaiser);

// Act
processRequest.Process(someJObject);

// Assert
eventRaiser.Received().RaiseEventForClient();

В качестве отдельной заметки, подумайтенемного о том, как вы называете свои классы. Большинство стандартов кодирования говорят, что имена классов должны быть названы с использованием существительного или существительной фразы и не должны заканчиваться на "Class".

Так что Client в порядке, но EventRaiserClass заканчивается Class. Рассмотрим что-то вроде EventRaiser.

ProcessRequest - это не существительное или не существительная фраза - это звучит как инструкция («обработайте этот запрос»), как правило, вы бы назвали метод,не класс. Рассмотрим что-то вроде RequestProcessor, который является объектом, который обрабатывает запросы.

1 голос
/ 21 октября 2019

Вы также можете проверить выброшенное событие в отношении sender и eventArgs . Если вы не хотите писать три метода тестирования для проверки всей процедуры поднятия события, тогда Nuclear.Test для вас.

[TestMethod]
void TestProcessRaisesEvent() {

    // arrange
    var eventRaiser = new EventRaiserClass();
    var processRequest = new ProcessRequest(eventRaiser);
    var json = default(JObject); // create your json
    Action action = () => processRequest.Process(json);

    // act / assert
    Test.If.RaisesEvent(eventRaiser, "SendEventToClient", action, out Object sender, out EventArgs e);
    Test.If.ReferencesEqual(eventRaiser, sender);
    Test.If.ValuesEqual(e, EventArgs.Empty);

}

Вам следует рассмотреть возможность тестирования EventRaiserClass иProcessRequest отдельно однако.

[TestMethod]
void TestEventRaiserRaisesEvent() {

    // arrange
    var eventRaiser = new EventRaiserClass();
    Action action = () => eventRaiser.RaiseEventForClient();

    // act / assert
    Test.If.RaisesEvent(eventRaiser, "SendEventToClient", action, out Object sender, out EventArgs e);
    Test.If.ReferencesEqual(eventRaiser, sender);
    Test.If.ValuesEqual(e, EventArgs.Empty);

}

[TestMethod]
void TestProcessRaisesEvent() {

    // arrange
    var eventRaiser = new EventRaiserClass();
    var processRequest = new ProcessRequest(eventRaiser);
    var json = default(JObject); // create your json
    Action action = () => processRequest.Process(json);

    // act / assert
    Test.If.RaisesEvent(eventRaiser, "SendEventToClient", action, out Object sender, out EventArgs e);

}

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