В настоящее время я борюсь с проблемой тестирования функции TPL
внутри оператора `RX. Проблема также в том, что у меня нет доступа к наблюдаемому.RX + TPL + Тестирование
Вот мой тест:
[Test]
public void TestRaceConditions()
{
// Arrange
TestScheduler testScheduler = new TestScheduler();
List<string> source = new List<string> {"Hello"};
List<string> results = new List<string>();
source.ToObservable().SelectMany(v => Task.Run(() =>
{
Thread.Sleep(10000); // Simulate long running operation
return v;
}).ToObservable(testScheduler))
.ObserveOn(testScheduler)
.Subscribe(s => results.Add(s));
// Act
testScheduler.Start();
Assert.That(results.Count, Is.EqualTo(1));
Assert.That(results[0], Is.EqualTo("Hello"));
}
Я гугл вокруг и нашел много статей и советов, как:
- Не смешивать
TPL
иRX
- Создать оболочку для
TPL
кода, где вы можете высмеивать и возвращать завершенную задачу. ==> А как насчет интеграционных тестов?
Я также попытался это создать пользовательский TaskScheduler
, но тогда я должен заменить каждый Task.Run
с Task.Factory.StartNew
.
Так что вопрос:
- Как получить контроль над задачей или наблюдаемой в тесте только с
Schedulers
, что я знаю, когда все элементы обработаны и закончили?
UPDATE: Реальный пример
public class ResultController : IDisposable
{
private readonly IServiceClient _serviceClient;
private readonly IDisposable _subscription;
public ResultController(IEventProvider eventProvider,
IServiceClient serviceClient,
ISchedulerProvider schedulerProvider)
{
_serviceClient = serviceClient;
_subscription = eventProvider.Events.SelectMany(e => LoadDataAsync(e.Id))
.SubscribeOn(schedulerProvider.TaskPool)
.ObserveOn(schedulerProvider.Dispatcher)
.Subscribe(OnNewDataLoaded);
}
private void OnNewDataLoaded(Data data)
{
}
public async Task<Data> LoadDataAsync(int id)
{
////return Task.Run(() =>
////{
//// Thread.Sleep(10000);
//// return new Data();
////});
return await _serviceClient.LoadDataByIdAsync(id);
}
public void Dispose()
{
_subscription.Dispose();
}
}
Это решение работает в производстве без проблем, но при тестировании у меня нет задачи под контролем.
- насмешливый
ServiceClient
и возвращение завершенноеTask
работает отлично. - Но в IntegrationTests с SpecFlow я не знаю, когда работа закончена без введения хакерских свойств для синхронизации.
Ответ заключается не в смешивании Rx и TPL. Просто используйте Rx. Зачем вам TPL? – Enigmativity
@Enigmativity Спасибо :-) Да, я знаю, но если у вас много кода, который уже использует задачи для загрузки некоторых данных с сервера. Это невозможно удалить. В производственном коде также не так. – crip
Можете ли вы показать фактический код, а не искусственный пример? – Enigmativity