Task 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: вот как я подписывался на observable
Exception error = null;
_sessionManager
.SyncSessions()
.Subscribe(null, e => error = e);
Assert.That(error, Is.Not.Null.After(500));
Я передаю null в первый параметр, поскольку меня это не очень волнует в контексте этого теста
1 ответ:
Во-первых, для исходного кода, который вы опубликовали, я рекомендую использовать AsyncSubject вместо
Теперь перейдем к вашему вопросу...ReplaySubject
. Считайте, что он оптимизирован для случая с одним результатом.Всякий раз, когда наблюдаемый источник генерирует исключение, это исключение распространяется через обработчик
OnError
. Если при подписке на observable вы не предоставляете обработчикOnError
, то будет выдано исключение.Маленький код вы опубликовано:
_sessionService.GetSessions(query).ToObservable().Select(SaveSessions);
Этого недостаточно. Не публикуя также код, который показывает, как ВЫ подписываетесь на observable, я могу только догадываться, что вы не предоставили обработчик
OnError
.Редактирование на основе тестового кода OP
Ваша фиктивная служба возвращает
Task
, которая создает исключение, или фиктивная служба просто создает исключение? Если вы не используете async / await, функцию, которая должна возвращатьTask
, но создает исключение при создании этогоTask
вызовет исключение немедленно вместо возврата failedTask
. ToObservable никогда даже не вызывается, потому что GetSessions бросает. Если вы измените свой макет службы, чтобы вернуть неудачныйTask
, то ваш тест, вероятно, будет работать правильно.Если вы хотите перехватывать немедленные исключения, а также неудачные задачи, то вы можете использовать
Defer
, чтобы отложить выполнение вашего метода до тех пор, пока наблюдатель не подпишется. Он также будет собирать сразу бросается исключениями в дополнение к искусству задачи:return Observable .Defer(() => _sessionService.GetSessions(query)) .Select(SaveSessions);