FakeItEasy: FakeItEasy.Core.FakeCreationException while creating (many) fakes
We are using FakeItEasy 2.0.0 and are creating thousands of fake objects during our unit-tests. Unfortunately we get a FakeItEasy.Core.FakeCreationException
occasionally in different test-classes for different fake-objects on our CI:
MESSAGE:
SetUp : FakeItEasy.Core.FakeCreationException :
Failed to create fake of type "IConditionElementCollector".
Below is a list of reasons for failure per attempted constructor:
No constructor arguments failed:
No usable default constructor was found on the type IConditionElementCollector.
An exception of type System.InvalidOperationException was caught during this call. Its message was:
Collection was modified; enumeration operation may not execute.
bei System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
bei System.Collections.Generic.List`1.Enumerator.MoveNextRare()
bei System.Collections.Generic.List`1.Enumerator.MoveNext()
bei Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.AddCustomAttributes(ProxyGenerationOptions proxyGenerationOptions)
bei Castle.DynamicProxy.Generators.BaseProxyGenerator.CreateTypeAttributes(ClassEmitter emitter)
bei Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope)
bei Castle.DynamicProxy.Generators.ClassProxyGenerator.<>c__DisplayClass1.<GenerateCode>b__0(String n, INamingScope s)
bei Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
bei Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options)
bei Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
bei Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
bei FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.GenerateClassProxy(Type typeOfProxy, IEnumerable`1 argumentsForConstructor, IInterceptor interceptor, IEnumerable`1 allInterfacesToImplement)
bei FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.DoGenerateProxy(Type typeOfProxy, IEnumerable`1 additionalInterfacesToImplement, IEnumerable`1 argumentsForConstructor, IInterceptor interceptor)
bei FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.CreateProxyGeneratorResult(Type typeOfProxy, IEnumerable`1 additionalInterfacesToImplement, IEnumerable`1 argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider)
+++++++++++++++++++
STACK TRACE:
bei FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithResolvedConstructors(Type typeOfFake, String reasonForFailureOfUnspecifiedConstructor, IEnumerable`1 resolvedConstructors)
bei FakeItEasy.Creation.FakeObjectCreator.TryCreateFakeWithDummyArgumentsForConstructor(Type typeOfFake, IProxyOptions proxyOptions, IDummyValueCreationSession session, String failReasonForDefaultConstructor, Boolean throwOnFailure)
bei FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, IProxyOptions proxyOptions, IDummyValueCreationSession session, Boolean throwOnFailure)
bei FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, Action`1 optionsBuilder)
bei FakeItEasy.Creation.DefaultFakeCreatorFacade.CreateFake[T](Action`1 optionsBuilder)
bei FakeItEasy.A.Fake[T]()
bei VisibilityPropertyHandlerTest.Setup()
Any idea, how to fix this Heisenbug? The tests are running sequentially on the CI (no tests are running concurrently). It happens about once every week at different locations, usually where a lot of fakes are created rapidly: in the unit-tests.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 17 (14 by maintainers)
I think so… @apacha, your tests are run serially, but are you sure the tested code doesn’t spawn threads that could indirectly create fakes (e.g. by calling an unconfigured method on a fake)?
@thomaslevesque, I think your analysis is spot on, but can’t see any way for there to be a problem if tests are run serially. Only concurrent fake creation should be a problem, no?
Thanks for reporting this @apacha.
I think the problem is in
CastleDynamicProxyGenerator
. Apparently we update the list ofAdditionalAttributes
(here) on a shared instance ofProxyGenerationOptions
, which causes this loop to fail if it happens at the same time. What is strange is that it really looks like a concurrency issue, but if you’re running your tests sequentially, you should never hit it…Anyway, if the root cause is what I think it is, it should be pretty easy to fix. The trouble is that it will be difficult to make sure it’s fixed, since it can’t be easily reproduced…