3

я следующий метод, который отвечает за вызов моего класса обслуживания и передачи результатов к другому способу их сохранения в моей БД:Задача ToObservable Обработка ошибок

public IObservable<bool> SyncSessions() 
{ 
    var subject = new ReplaySubject<bool>(); 

    try 
    { 
     var query = new ByFilterQuery { SearchPeriodStartTime = DateTime.Now }; 
     var sessions = _sessionService.GetSessions(query).Result; 
     var saved = SaveSessions(sessions); 
     subject.OnNext(saved); 
     subject.OnCompleted(); 
    } 
    catch (Exception ex) 
    { 
     subject.OnError(ex); 
    } 

    return subject; 
} 

_sessionService.GetSessions будет бросать HttpRequestException если сервер возвращает 500 или что-то подобное. У меня есть единичный тест, который издевается над этим поведением и хочет протестировать мой метод, который обрабатывает ошибку изящно.

Есть ли лучшие способы распространения ошибки в режиме Rx? Я пробовал делать:

_sessionService.GetSessions(query).ToObservable().Select(SaveSessions); 

Но это моя ошибка кинул вместо него передается на обработку ошибок действий в вызывающем методе. Я также планирую объединить этот метод с несколькими другими и обработать ошибки в объединенной усадьбе.

EDIT: Вот как я подписавшись на наблюдаемом

Exception error = null; 
_sessionManager 
    .SyncSessions() 
    .Subscribe(null, e => error = e); 

Assert.That(error, Is.Not.Null.After(500)); 

Я передаю нуль в качестве первого параметра, как я на самом деле не волнует, что в контексте этого теста

ответ

2

Во-первых, для исходного кода, который вы опубликовали, я рекомендую использовать AsyncSubject вместо ReplaySubject. Подумайте об этом как о оптимизированном для случая с одним результатом.

Теперь на ваш вопрос ...

Всякий раз, когда наблюдаемый источник генерирует исключение, то исключение распространяется через OnError обработчика. Если, когда вы подписываетесь на наблюдаемое, вы не предоставляете обработчик OnError, тогда исключение будет выбрано.

Небольшой код размещен:

_sessionService.GetSessions(query).ToObservable().Select(SaveSessions); 

недостаточно. Не отправляя код, который показывает, как вы подписываетесь на наблюдаемый, я могу только предположить, что вы не предоставили обработчик OnError.

Edit на основе тестового кода OP в

Ваш фиктивный сервис возвращает Task, который генерирует исключение, или макет службы просто бросает исключение? Если вы не используете async/await, то функция, которая должна возвращать Task, но генерирует исключение, создавая то, что Task немедленно восстановят исключение, вместо того, чтобы возвращать неудачный Task. ToObservable никогда даже не вызван, потому что GetSessions бросает. Если вы измените свой макет службы, чтобы вернуть сбой Task, ваш тест, вероятно, будет работать правильно.

Если вы хотите уловить немедленные исключения, а также неудачные задачи, вы можете использовать Defer для отсрочки выполнения вашего метода до тех пор, пока не будет подписан наблюдатель. Она также будет собирать любые немедленно брошенные исключения в дополнении к неудавшимся задачам:

return Observable 
    .Defer(() => _sessionService.GetSessions(query)) 
    .Select(SaveSessions); 
+0

Добавлено подписавшись кодом – JFoulkes

+0

Test бросает ошибку. GetSessions() имеет вызов response.EnsureSuccessStatusCode(); поэтому может возникнуть ошибка – JFoulkes

Смежные вопросы