Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

System.AppDomainUnloadedException when running UnitTests with RC2 #203

Closed
divega opened this issue Jun 7, 2016 · 16 comments
Closed

System.AppDomainUnloadedException when running UnitTests with RC2 #203

divega opened this issue Jun 7, 2016 · 16 comments
Assignees

Comments

@divega
Copy link

divega commented Jun 7, 2016

From @Mertsch on June 3, 2016 12:20

After the upgrade from RC1 to RC2 some of my Unit Tests which test against the DB fail with the following exception.
The behavior is reproducible, BUT only happens in a certain combination of tests. So I can't give a direct example as I am unable to find out which combination of my 90 tests causes this.
Fact is each tests runs fine on its own, all ran fine together with RC1, all tests run fine under R# Test runner, TFS (VSTS) / Test in VS show the same behavior.

The line where the test fails is a DBContext accessor, but many other DBContext operations have been successful before the specific one.

Someone else seems to have the same issue
http://stackoverflow.com/questions/37378698/ef-core-rc2-appdomainunloadedexception
I am not using any In-Memory provider, only pure SQL Server

Each Unit Test builds up a completely new DI context, so that nothing is shared between Tests in any (static) way

Error Message:
   Test method xxx.ServiceTests.CleanupSuggestedTest threw exception: 
System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
Stack Trace:
    at System.Runtime.Remoting.ObjectHandle.Unwrap()
   at Microsoft.Extensions.Caching.Memory.CacheEntryHelper.get_Scopes()
   at Microsoft.Extensions.Caching.Memory.CacheEntryHelper.EnterScope(CacheEntry entry)
   at Microsoft.Extensions.Caching.Memory.MemoryCache.CreateEntry(Object key)
   at Microsoft.Extensions.Caching.Memory.CacheExtensions.Set[TItem](IMemoryCache cache, Object key, TItem value)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddAsyncQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at yyy.SomeService.<SavePackage>d__6.MoveNext() in C:\Build\_work\22\s\<Project>\Services\SomeService.cs:line 56
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at xxx.ServiceTests.<CleanupSuggestedTest>d__1.MoveNext() in C:\Build\_work\22\s\<Project>.Tests\ServiceTests.cs:line 75
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)

Copied from original issue: dotnet/efcore#5643

@divega
Copy link
Author

divega commented Jun 7, 2016

Moving to caching given the contents of the stack. @Tratcher this is the one I told you about.

@Tratcher
Copy link
Member

Tratcher commented Jun 7, 2016

@Tratcher
Copy link
Member

Tratcher commented Jun 7, 2016

@sebastienros?

@Tratcher
Copy link
Member

Tratcher commented Jun 7, 2016

AppDomains, must be net451...

@Mertsch
Copy link

Mertsch commented Jun 8, 2016

targeting net46 on system with net461 to be precise

@muratg muratg added this to the 1.0.1 milestone Jun 9, 2016
@muratg
Copy link

muratg commented Jun 9, 2016

Interesting. When upgrading to RC2, I assume you upgraded xunit too?

Looks like something weird's going on with the appdomains which I think xunit uses.

@Mertsch
Copy link

Mertsch commented Jun 9, 2016

@muratg Actually it's MSTest I am not running under .NET Core, I am "only" using the framework inside a classic .NET app, tested with traditional MSTest

@muratg
Copy link

muratg commented Jun 9, 2016

@Mertsch You mean a .csproj based project instead of a project.json based one?

@Mertsch
Copy link

Mertsch commented Jun 9, 2016

@muratg Exactly.

@frankseibel
Copy link

I'm seeing the same issue. I have a plain old .NET class library using RC2 which I'm running MSTest tests against.

@frankseibel
Copy link

frankseibel commented Jun 14, 2016

Let me add a little more to what I'm seeing. I have about 140 unit tests against several MVC 5 (ASP.NET 4.6) controllers which reference a class library using Entity Framework Core 1.0 RC2. When running the unit tests it gets through about 5 of them before getting the AppDomainUnloadedException. I can then run the failed unit tests and get through another group before getting the exception again. After 3 or 4 attempts they finally complete. Unfortunately in our automated build this will fail our build.

This was not happening with the same unit tests under RC1.

@frankseibel
Copy link

We were able to get past this issue. It seemed that methods on our controllers were asynchronous and the tests were not waiting for the threads to complete before continuing. This wasn't an issue until we upgraded to RC2. I'm not sure why our tests worked before to begin with. Either way, once we waited for the threads to complete this issue went away.

@vmsgsp
Copy link

vmsgsp commented Jul 5, 2016

We have the same issue. When calling DatabaseContext.Set.SingleOrDefault(this IQueryable source, Expression<Func<TSource, bool>> predicate) we get the AppDomainUnloadedException below.

  • Running synchronously, no threads, no tasks.
  • .NET 4.6.1
  • MS Unit test.
  • Visual Studio 2013
  • Did not happen with Entity Framework 7.0.0-rc1 (Caching 1.0.0-rc1). This problem just came up when migrating to Entity Framework Core 1.0.0.
  • Same behavior as described by frankseibel (tests pass in smaller sub-groups when being re-run again and again).

The exception only occurs if tests from DIFFERENT MS TEST PROJECTS are executed within the same test run. Through debugging in [AssemblyInitialize] of the test projects, I see that they are run in different app domains. So maybe when it comes to the next test project your MemoryCache still has references to the previous app domain from the previous test project?

Maybe the issue is related to the commit f15fb80, because there this Remoting.ObjectHandle.Unwrap has been introduced.

DatabaseContext.Set<T>.SingleOrDefault<TSource>(this IQueryable source, Expression<Func<TSource, bool>> predicate);
throws
System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
Result StackTrace:
at System.Runtime.Remoting.ObjectHandle.Unwrap()
at Microsoft.Extensions.Caching.Memory.CacheEntryHelper.get_Scopes()
at Microsoft.Extensions.Caching.Memory.CacheEntryHelper.GetOrCreateScopes()
at Microsoft.Extensions.Caching.Memory.CacheEntryHelper.EnterScope(CacheEntry entry)
at Microsoft.Extensions.Caching.Memory.CacheEntry..ctor(Object key, Action1 notifyCacheEntryDisposed, Action1 notifyCacheOfExpiration)
at Microsoft.Extensions.Caching.Memory.MemoryCache.CreateEntry(Object key)
at Microsoft.Extensions.Caching.Memory.CacheExtensions.Set[TItem](IMemoryCache cache, Object key, TItem value)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)

@vmsgsp
Copy link

vmsgsp commented Jul 5, 2016

Now I found the root-cause in my case:
The exception occurs when tests of different MS test projects are run. All of the test projects are run within the SAME PROCESS. But every MS test project is executed in a DIFFERENT APP DOMAIN.
It seems that the MemoryCache still refers to items belonging to the previous app domain which already has been unloaded (when the previous MS test project run within the same process has terminated).

In my case the following WORKAROUND helps to overcome this limitation:
In the MSTest [AssemblyInitialize] call
System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("CacheEntry.Scopes", null);
which "clears the memory cache".

No idea, whether this workaround has other bad side-effects!

And of course this should be fixed in Microsoft.Extensions.Caching.Memory.CacheEntryHelper as soon as possible.

@BrennanConroy
Copy link
Member

27a2072

@andresmoschini
Copy link

Good job @BrennanConroy fixing this issue!

Sadly @vmsgsp workaround does not work for me.

I am working with version 1.0.0, do you think that is there a simple and minimalist way to apply the fix in my code base?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants