Mock HostingEnvironment.QueueBackgroundWorkItem в тесте xunit
У меня есть метод, использующий
HostingEnvironment.QueueBackgroundWorkItem
, который я хочу unit test выполнить некоторое поведение перед этим вызовом, однако тест не работает с System.InvalidOperationException : Operation is not valid due to the current state of the object.
Я подозреваю, что мне нужно высмеять HostingEnvironment, но не знает, как это сделать.
Ответы
Ответ 1
Чтобы решить эту проблему, я определил интерфейс
public interface ITaskScheduler
{
void QueueBackgroundWorkItem(Action<CancellationToken> workItem);
}
В производственном коде я внедряю реализацию
public class AspNetTaskScheduler : ITaskScheduler
{
public void QueueBackgroundWorkItem(Action<CancellationToken> workItem)
{
HostingEnvironment.QueueBackgroundWorkItem(workItem);
}
}
В тестовом коде я внедряю реализацию
public class TaskScheduler : ITaskScheduler
{
public void QueueBackgroundWorkItem(Action<CancellationToken> workItem)
{
workItem.Invoke(new CancellationToken());
}
}
Я думаю, что это ОК, так как модульные тесты работают, а мои классы, которые ставят очередь фоновых задач, отключаются от HostingEnvironment
.
Ответ 2
Я сделал это, чтобы все было просто:
/// <summary>
/// add some jobs to the background queue
/// </summary>
public static class BackgroundTaskScheduler
{
/// <summary>
/// send the work item to the background queue
/// </summary>
/// <param name="workItem">work item to enqueue</param>
public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem)
{
try
{
HostingEnvironment.QueueBackgroundWorkItem(workItem);
}
catch (InvalidOperationException)
{
workItem.Invoke(new CancellationToken());
}
}
}
Затем для запуска задания просто:
BackgroundTaskScheduler.QueueBackgroundWorkItem(ct =>
{
// bla
});
Ответ 3
Немного аккуратно, чем вызов HostingEnvironment.QueueBackgroundWorkItem
, независимо от того, существует ли ASP.NET AppDomain, а затем ловит InvalidOperationException
:
public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem)
{
if (HostingEnvironment.IsHosted)
{
HostingEnvironment.QueueBackgroundWorkItem(workItem);
}
else
{
workItem.Invoke(new CancellationToken());
}
}