После обновления до Castle Trunk и NHibernate 2.1.0.4000 мои интеграционные тесты вылетают TestDriven.Net

У меня есть старый MonoRail/ActiveRecord, я тоже немного поработал.

Недавно я решил обновить приложение до Castle Trunk & NHibernate 2.1.0.4000 GA, и теперь я обнаружил несколько проблем с запуском тестов:

Во-первых, при использовании TestDriven.Net для запуска интеграционных тестов, которые работают с базой данных, происходит полный сбой TestDriven.Net или выполнение всех тестов завершается, а затем TestDriven.Net зависает. Такого никогда не было до обновления.

Когда TestDriven.Net дает сбой, вот что записывается в журнал событий:

Ведро ошибок 1467169527, тип 1 Имя события: APPCRASH Ответ: Недоступно Идентификатор кабины: 0

Сигнатура проблемы: P1: ProcessInvocation86.exe P2: 2.22.2468.0 P3: 4a26845c P4: KERNELBASE.dll P5: 6.1.7600.16385 P6: 4a5bdbdf P7: e053534f P8: 0000b727 P9: P10:

Во-вторых, исключения регистрируются, когда прокси-классы Finalize()'d, как показано ниже, похоже, когда это регистрируется пару раз, то есть при сбое TestDriven.Net.

Вот трассировка стека для исключения:

NHibernate.LazyInitializationException:     
Initializing[MyApp.Core.Models.TestExecutionPackage#15d9eb96-faf0-4b4b-9c5c-9cd400065430]-Could not initialize proxy - no Session.
  at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
  at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
  at NHibernate.ByteCode.Castle.LazyInitializer.Intercept(IInvocation invocation)
  at Castle.DynamicProxy.AbstractInvocation.Proceed()
  at Castle.Proxies.TestExecutionPackageProxy.Finalize()

Такое же поведение также приведет к сбою MsBuild на нашем сервере CI.

Что действительно странно, так это то, что теоретически исключения, созданные в Finalize(), должны быть проглочены в соответствии с документами MSDN:

http://msdn.microsoft.com/en-us/library/system.object.finalize(VS.71).aspx

Если Finalize или переопределение Finalize вызывает исключение, среда выполнения игнорирует исключение, завершает этот метод Finalize и продолжает процесс финализации.

Кто-нибудь думает?


person Bittercoder    schedule 02.12.2009    source источник
comment
Я не уверен, что DynamicProxy должен когда-либо переопределять метод Finalize... в первую очередь   -  person Krzysztof Kozmic    schedule 03.08.2010


Ответы (2)


Никогда не доходил до сути этой проблемы, но в итоге я реализовал довольно элементарный обходной путь, создав собственную реализацию LazyInitializer, где я проверяю метод Finalize при вызове, как показано ниже:

/// <summary>
/// Invoke the actual Property/Method using the Proxy or instantiate the actual
/// object and use it when the Proxy can't handle the method. 
/// </summary>
/// <param name="invocation">The <see cref="IInvocation"/> from the generated Castle.DynamicProxy.</param>
public virtual void Intercept(IInvocation invocation)
{
  try
  {
    if (invocation.Method.Name == "Finalize")
    {
      return;
    }
    if (_constructed)
    {
      // let the generic LazyInitializer figure out if this can be handled
      // with the proxy or if the real class needs to be initialized
      invocation.ReturnValue = base.Invoke(invocation.Method, invocation.Arguments, invocation.Proxy);

      // the base LazyInitializer could not handle it so we need to Invoke
      // the method/property against the real class
      if (invocation.ReturnValue == InvokeImplementation)
      {
        invocation.ReturnValue = invocation.Method.Invoke(GetImplementation(), invocation.Arguments);
        return;
      }
      else
      {
        return;
      }
    }
    else
    {
      // TODO: Find out equivalent to CGLIB's 'method.invokeSuper'.
      return;
    }
  }
  catch (TargetInvocationException tie)
  {
    // Propagate the inner exception so that the proxy throws the same exception as
    // the real object would 
    Exception_InternalPreserveStackTrace.Invoke(tie.InnerException, new Object[] { });
    throw tie.InnerException;
  }
}
person Bittercoder    schedule 03.12.2009

У меня была такая же проблема, когда я перешел на версию 2.1.2 NHibernate. Я поменял Castle на LinFu Proxy, после чего у меня все заработало. Надеюсь это поможет.

person Marclei Silva    schedule 02.08.2010