2014-10-22 15 views
5

Kiểm tra đơn vị sử dụng FakeItEasy ngẫu nhiên thất bại khi cố gắng giả mạo một intefrace đơn giản. Nó xảy ra trong các bài kiểm tra khác nhau đôi khi và không ổn định.FakeItEasy đôi khi không tạo được giả khi các thử nghiệm được chạy song song

Đây là một giao diện mẫu tôi cần phải giả:

public interface IJobSuiteFilterApplier 
{ 
    JobSuiteDto FilterJobSuites(JobSuiteDto jobSuiteDto, JobSuiteFilter jobSuiteFilter); 
} 

Dưới đây là đoạn mã mà tạo ra các giả mạo và thất bại đôi khi:

var jobSuiteFilterApplier = A.Fake<IJobSuiteFilterApplier>(x => x.Strict()); 

Dưới đây là các chi tiết ngoại lệ:

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) 

Khi tôi thêm thông tin sau đây, kiểm tra vượt qua, nhưng có vẻ lạ lùng mà tôi cần thêm nó vào tất cả các fa ke tạo:

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())); 

    } 
} 

Cập nhật: Tôi đang chạy các bài kiểm tra sử dụng runner thử nghiệm ReSharper trên máy tính phát triển và sử dụng mstext.exe trên build server. Cài đặt đồng thời cho phép chạy nhiều thử nghiệm cùng một lúc.

+0

Bạn đang sử dụng khung kiểm tra đơn vị nào? Bạn có chạy thử nghiệm đơn vị song song hoặc tạo hàng giả trên nhiều luồng không? Điều đó có vẻ là một [vấn đề mở] (https://github.com/FakeItEasy/FakeItEasy/issues/60). –

+0

Xin lỗi vì đã không đề cập đến nó. Tôi đang sử dụng FakeItEasy. Tôi đang chạy các bài kiểm tra bằng cách sử dụng thử nghiệm ReSharper Á hậu trên máy phát triển và sử dụng mstext.exe trên máy chủ xây dựng. –

Trả lời

10

Cập nhật: FakeItEasy 2.0.0 đã cải thiện đáng kể hỗ trợ cho các thử nghiệm chạy song song. Thử nó.

như mike z được đề cập: FakeItEasy hiện không hỗ trợ kiểm tra nhiều luồng. Điều này là do không phải tất cả nội bộ đều an toàn theo luồng và không dễ dàng làm cho toàn bộ chuỗi an toàn. Đã xảy ra sự cố mở, number 60, để hỗ trợ thực thi kiểm tra đa luồng.

Hiện tại, giải pháp bạn cung cấp là cách duy nhất để đạt được điều này, như được giải thích ban đầu ở đây http://hmemcpy.com/2012/12/running-multithreaded-unit-tests-with-fakeiteasy/.

Không có cách nào trên toàn cầu thêm một người biết lắng nghe đánh chặn cho tất cả hàng giả, tuy nhiên bạn có thể sử dụng lớp FakeConfigurator<T> để tự động hóa hành vi này mỗi loại, vì vậy bạn có thể chọn để bao gồm, đối với mỗi giả loại, một lớp học như

public class SomeTypeSynchronousConfigurator : FakeConfigurator<ISomeType> 
{ 
    public override void ConfigureFake(ISomeType fakeObject) 
    { 
     Fake.GetFakeManager(fakeObject) 
       .AddInterceptionListener(new CallSynchronizer()); 
    } 
} 

FakeItEasy sẽ discover the class và mọi giả mới (trong trường hợp này) ISomeType sẽ có Synchronizer áp dụng-bạn có thể làm giả giống như var fake = A.Fake<ISomeType>();.

+0

Cảm ơn bạn đã trả lời. –

+0

+1 Philipp cho câu trả lời và +1 Blair cho chỉnh sửa tốt đẹp! –

Các vấn đề liên quan