2014-10-22 5 views
5

Модульные тесты, которые используют FakeItEasy, случайным образом не срабатывают при попытке подделать простое 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) 

Когда я добавляю следующее, тесты проходят, но это выглядит странно, что мне нужно добавить его ко всем fa создание Ke:

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

Какая модульная тестовая среда вы используете? Вы выполняете параллельные тесты или создаете подделки на нескольких потоках? Кажется, это [открытая проблема] (https://github.com/FakeItEasy/FakeItEasy/issues/60). –

+0

Извините, что не упоминал об этом. Я использую FakeItEasy. Я запускаю тесты с помощью тестового бегуна ReSharper на машине разработчика и используя mstext.exe на сервере сборки. –

ответ

10

Обновление: FakeItEasy 2.0.0 имеет значительно улучшенную поддержку при параллельном тестировании. Попробуй.

как указано в mike z: 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>();.

+0

Спасибо за ваш ответ. –

+0

+1 Филипп за ответ и +1 Блэр за красивое украшение! –

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

  • Нет связанных вопросов^_^