2015-03-19 4 views
0

Я использую PostSharp MethodInteceptionAspect в моем проекте ASP.NET MVC. Он отлично работает, но я хочу проверить свои аспекты в модульных тестах. Когда я добавляю аспект к любому методу в единичном тесте он компилирует нормально, но он не во время выполнения с этим сообщением:Использование PostSharp в модульных тестах

Unable to create instance of class PNAF.Tests.Auth.DatabaseSessionScopeAspectTests. Error: System.TypeInitializationException: The type initializer for 'PostSharp.ImplementationDetails_e613b708.<>z__a_1' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object.. 
    at PNAF.Core.IoC.ServiceLocator.Resolve() in ServiceLocator.cs: line 17 
    at PNAF.Modules.Auth.Aspects.DatabaseSessionScopeAttribute.RuntimeInitialize(MethodBase method) in DatabaseSessionScopeAttribute.cs: line 24 
    at PostSharp.ImplementationDetails_e613b708.<>z__a_1..cctor() in :line 0 
--- End of inner exception stack trace --- 
    at PostSharp.ImplementationDetails_e613b708.<>z__a_1.Initialize() 
    at PNAF.Tests.Auth.DatabaseSessionScopeAspectTests..cctor() in :line 0 

Компиляция применяет аспект PostSharp (я проверил скомпилированный MSIL), но во время выполнения я могу» t создавать экземпляры классов, которые перехватили методы.

Это происходит только при выполнении тестов. Перехват проекта ASP.NET MVC в порядке.

Пример модульного теста, который использует PostSharp аспект:

[TestClass] 
public class DatabaseSessionScopeAspectTests : TestBase 
{ 
    [TestMethod] 
    public void DataSessionScopeTest() 
    { 
     var data = GetData(); 
     Assert.IsNotNull(data); 
    } 

    [DatabaseSessionScope] // this is PostSharp MethodInterceptionAspect 
    private IList<User> GetData() 
    { 
     // some code 
    } 
} 

BTW: Я использую VS Unit Testing Framework.


EDIT:

я узнал, что, когда я удаляю частную собственность в аспекте он работает.

аспект выглядел следующим образом:

public class DatabaseSessionScopeAttribute : MethodInterceptionAspect 
{ 
    private IDatabaseSessionProvider databaseSessionProvider; 

    public override void RuntimeInitialize(MethodBase method) 
    { 
     base.RuntimeInitialize(method); 
     databaseSessionProvider = ServiceLocator.Resolve<IDatabaseSessionProvider>(); 
    } 

    public override void OnInvoke(MethodInterceptionArgs args) 
    { 
     // some code 
    } 
} 

Когда я удалить IDatabaseSessionProvider он работает отлично, как и ожидалось.

Может ли кто-нибудь объяснить, почему это необходимо? Я не понимаю, почему он работает в веб-проекте, но не в проекте модульного тестирования.

+2

Как это атрибут сферы сеанса базы данных вам не хватает настройку конфигурации в тестовом проекте блока? Например, строка подключения к базе данных? –

+0

Нет, когда я удаляю аспект и создаю сеанс базы данных в самом методе, он работает. Это не удается, даже если я не вызываю метод только потому, что класс содержит аспект. –

ответ

1

Кажется, что RuntimeInitialize вызывается до инициализации контейнера IoC. Самым простым решением может быть ленивый инициализировать databaseSessionProvider. В дополнение к этому databaseSessionProvider поле должно быть помечено как NonSerializable.

EDIT Пример: устанавливается в соответствии с возражением Мартина

[Serializable] 
public class DatabaseSessionScopeAttribute : MethodInterceptionAspect 
{ 
    [NonSerialized] 
    private Lazy<IDatabaseSessionProvider> databaseSessionProvider; 

    public override void RuntimeInitialize(MethodBase method) 
    { 
     base.RuntimeInitialize(method); 
     databaseSessionProvider = 
      new Lazy<IDatabaseSessionProvider>(SomeSessionProviderFactoryMethod); 
    } 

    private static IDatabaseSessionProvider SomeSessionProviderFactoryMethod() 
    { 
     return ServiceLocator.Resolve<IDatabaseSessionProvider>(); 
    } 
} 
+0

Да, это, наверное, причина. Ваш код работает после незначительных изменений. Мне пришлось поместить inicialization ленивого поля в метод RuntimeInitialize(), потому что конструктор аспектов не вызывается. Если вы отредактируете свой ответ, я помечаю его как принятый ответ. –

+0

Да, вы абсолютно правы. Ответ исправлен. Спасибо, что указали это. –

Смежные вопросы