2015-04-13 4 views
0

Я делаю unittests для приложения asp.net. Из-за того, как класс, я в настоящее время тестирования предназначена она использует несколько потоков и, таким образом, вручную устанавливает язык для одного из нитей:Как установить UserLanguages ​​для модульных тестов (используя смешные контексты http)?

Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(HttpContext.Current.Request.UserLanguages[0]); 

Для этой работы я насмешливый HttpContext, используя следующий класс в UnitTests, прежде чем запускать класс, который содержит приведенный выше код:

public class HttpContextMock 
{ 
    public static HttpContext MockedHttpContext() 
    { 
     var httpRequest = new HttpRequest("", "MyUrl", ""); 
     var stringWriter = new StringWriter(); 
     var httpResponse = new HttpResponse(stringWriter); 
     var httpContext = new HttpContext(httpRequest, httpResponse); 

     var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(), 
               new HttpStaticObjectsCollection(), 10, true, 
               HttpCookieMode.AutoDetect, 
               SessionStateMode.InProc, false); 

     httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance, 
            null, CallingConventions.Standard, 
            new[] { typeof(HttpSessionStateContainer) }, 
            null) 
          .Invoke(new object[] { sessionContainer }); 

     return httpContext; 
    } 

Теперь проблема даже если я получаю правильное HttpContext команды

HttpContext.Current.Request.UserLanguages 

Всегда г eturns null.

Итак, мой вопрос заключается в том, что можно сделать, чтобы гарантировать, что UserLanguages ​​возвратят хотя бы 1 запись?

ответ

0

Извержение HTTPContext не так просто, как вы только что узнали.

Почему бы не избежать этого вообще?

Вместо

Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(HttpContext.Current.Request.UserLanguages[0]); 

Вы могли бы сделать что-то вроде

Thread.CurrentThread.CurrentUICulture = _ContextSpecificSettings.Language; 

Где _ContextSpecificSettings является экземпляром класса вы закодировать себя. Может быть что-то вроде:

class ContextSpecificSettings 
{ 
    HTTPContext _HTTPContext; 

    public ContextSpecificSettings() 
    { 
     _HTTPContext = HTTPContext; 
    } 

    public string Language // used string but you would of course use here whatever type is used in UserLanguages 
    { 
     get { return _HttpContext.Current.Request.UserLanguages[0]; } 
    } 
} 

Теперь, вместо того, чтобы пытаться дразнить HttpContext, у вас есть только глумиться/незавершенная свой собственный класс ContextSpecificSettings. Это намного проще сделать, потому что все, что вам нужно, чтобы mock/stub возвращает язык, который вы хотите использовать в своем тесте.

Все, что осталось сделать, это убедиться, что класс, содержащий это присвоение, Thread.CurrentThread.CurrentUICulture достает экземпляр вашего класса ContextSpecificSettings. Вы можете сделать это с помощью простой инсталляции конструктора. Например:

class SomeThreadUsingClass 
{ 
    ContextSpecificSettings _Settings; 

    public SomeThreadContextUsingClass(ContextSpecificSettings useThisSettingsInstance) 
    { 
     _Settings = useThisSettingsInstance; 
    } 

    public Int SomeMethodUsingLanguage() 
    { 
     // <snip> 
     Thread.CurrentThread.CurrentUICulture = _Settings.Language; 
     // <snip> 
     return Whatever; 
    } 
} 

При создании экземпляра SomeThreadUsingClass в Вашем коде, вы передать его (новый) экземпляр ContextSpecificSettings класса. Когда вы создаете экземпляр SomeThreadUsingClass в тесте, все, что вам нужно сделать, это передать ему экземпляр класса ContextSpecificSettings Mock/Stub.

Кстати, это та же техника, что описана в статье Property.Settings.Default makes it hard to unit test any method that uses it