Если вы используете фиктивную библиотеку, попробуйте переместить код, не подлежащий тестированию, в службу:
interface IThreadCultureSetter
{
void SetCurrentThreadCulture(CultureInfo ci, [CallerMemberName]string callerMethod = null);
}
class ThreadCultureSetter : IThreadCultureSetter
{
public void SetCurrentThreadCulture(CultureInfo ci, [CallerMemberName]string callerMethod = null)
{
// Set thread culture
}
}
Измените действие контроллера для использования интерфейса:
private readonly IThreadCultureSetter _cultureSetter;
public async Task<ActionResult> Index()
{
// Look up user in database
var dbUser = database.GetUser(User.Identity.GetUserId());
// Set preferred culture
_cultureSetter.SetCurrentThreadCulture(new CultureInfo(dbUser.PreferredCulture));
// Do some other work
await DoAsynchronousWork();
return View();
}
В своем тесте укажите фиктивное IThreadCultureSetter
и убедитесь, что метод был вызван с нужным CultureInfo
:
// Assume you use Moq
Mock<IThreadCultureSetter> cultureSetterMock;
// The SetCurrentThreadCulture must be called by Index method
mock.Verify(x => x.SetCurrentThreadCulture(It.Is<CultureInfo>(ci => ci.Name == "de"), "Index"));
Дело в том, что Thread.CurrentThread.CurrentCulture
является асинхронным c stati c (значение хранится в AsyncLocal) и не подходит для тестирования, поскольку его значение существует только для текущего захваченного асинхронного объема c.
ОБНОВЛЕНИЕ
Я только что понял, что можно использовать пользовательский SynchronizationContext
для проверки того, что культура потока была установлена (не может гарантировать, чем) как ожидаемая культура:
class ThreadCultureInspectionSynchronizationContext : SynchronizationContext
{
private readonly string _expectedCultureName;
public ThreadCultureInspectionSynchronizationContext(string expectedCultureName)
{
_expectedCultureName = expectedCultureName;
}
public bool WasSetToExpected { get; private set; }
public override void Post(SendOrPostCallback d, object state)
{
// When context is switching, e.g. continuation of an await being executed, this method is called.
// This method could inspect on thread culture, and set flag to true once expected culture detected.
// This method can only prove that the thread culture was set, but cannot suggest by which method.
if (!WasSetToExpected)
{
WasSetToExpected = Thread.CurrentThread.CurrentCulture.Name.Dump() == _expectedCultureName;
}
base.Post(d, state);
}
}
В вашем тесте перед вызовом Index
:
var ctx = new ThreadCultureInspectionSynchronizationContext("de");
SynchronizationContext.SetSynchronizationContext(ctx);
await Index();
...
Assert.IsTrue(ctx.WasSetToExpected);
Если ваша культура потока была установлена методом Index
, вы ожидаете увидеть все проверки на культуре потоков по контексту синхронизации - ваш ожидаемый.