在尝试伪造简单的intefrace时,使用FakeItEasy的单元测试会随机失败。它偶尔会在不同的测试中出现并且不稳定。
以下是我需要伪装的示例界面:
public interface IJobSuiteFilterApplier
{
JobSuiteDto FilterJobSuites(JobSuiteDto jobSuiteDto, JobSuiteFilter jobSuiteFilter);
}
以下是创建假冒的代码片段,有时会失败:
var jobSuiteFilterApplier = A.Fake<IJobSuiteFilterApplier>(x => x.Strict());
以下是例外情况:
FakeItEasy.Core.FakeCreationException:
Failed to create fake of type "QS.TestShell.Server.ExecutionPlanner.Queries.IExecutionPlannerQueryService".
Below is a list of reasons for failure per attempted constructor:
No constructor arguments failed:
No usable default constructor was found on the type QS.TestShell.Server.ExecutionPlanner.Queries.IExecutionPlannerQueryService.
An exception was caught during this call. Its message was:
Collection was modified; enumeration operation may not execute.
at FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithResolvedConstructors(Type typeOfFake, String reasonForFailureOfUnspecifiedConstructor, IEnumerable`1 resolvedConstructors)
at FakeItEasy.Creation.FakeObjectCreator.TryCreateFakeWithDummyArgumentsForConstructor(Type typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession session, String failReasonForDefaultConstructor, Boolean throwOnFailure)
at FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession session, Boolean throwOnFailure)
at FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, FakeOptions options)
at FakeItEasy.Creation.DefaultFakeCreatorFacade.CreateFake[T](Action`1 options)
at FakeItEasy.A.Fake[T](Action`1 options)
当我添加以下内容时,测试通过,但看起来很奇怪,我需要将它添加到所有虚假创作中:
var jobSuiteFilterApplier = A.Fake<IJobSuiteFilterApplier>(x => x.Strict().Synchronized());
public class CallSynchronizer : IInterceptionListener
{
private static readonly object SynchronizationLock = new object();
public void OnBeforeCallIntercepted(IFakeObjectCall interceptedCall)
{
Monitor.Enter(SynchronizationLock);
}
public void OnAfterCallIntercepted(ICompletedFakeObjectCall interceptedCall, IFakeObjectCallRule ruleThatWasApplied)
{
Monitor.Exit(SynchronizationLock);
}
}
public static class MyPersonalFakeExtensions
{
public static IFakeOptionsBuilder<T> Synchronized<T>(this IFakeOptionsBuilder<T> builder)
{
return builder.OnFakeCreated(fake => Fake.GetFakeManager(fake).AddInterceptionListener(new CallSynchronizer()));
}
}
更新:我在开发人员计算机上使用ReSharper测试运行器并在构建服务器上使用mstext.exe运行测试。并发设置允许一次运行多个测试。
答案 0 :(得分:10)
更新:FakeItEasy 2.0.0大大改进了对并行运行的测试的支持。试试吧。
正如迈克提到的那样:FakeItEasy目前不支持多线程测试。这是因为并非所有内部都是线程安全的,并且使其完全线程安全并不容易。有一个未解决的问题number 60,用于支持多线程测试执行。目前,您提供的解决方案是实现此目标的唯一方法,正如此处http://hmemcpy.com/2012/12/running-multithreaded-unit-tests-with-fakeiteasy/所述。
无法为所有假冒全局添加拦截侦听器,但是您可以使用FakeConfigurator<T>
类自动执行每种类型的行为,因此您可以选择包含,每个伪造的类型,如
public class SomeTypeSynchronousConfigurator : FakeConfigurator<ISomeType>
{
public override void ConfigureFake(ISomeType fakeObject)
{
Fake.GetFakeManager(fakeObject)
.AddInterceptionListener(new CallSynchronizer());
}
}
FakeItEasy将discover the class并且每个新假(在这种情况下)ISomeType
都会应用同步器 - 您可以像var fake = A.Fake<ISomeType>();
一样伪造。