2013-03-08 59 views
16

所以我試圖建立一個端到端的集成測試套件與RavenDB和ServiceStack,但我遇到了一個很奇怪的問題,即驗證不上一些要求運行。這真的很奇怪,我不確定我做錯了什麼。我正在使用NCrunch。有時測試通過,有時失敗。ServiceStack驗證並非總是射擊

希望這是一個簡單的辦法和一些骨爲首我做的。

,你可以下載http://github.com/khalidabuhakmeh/endtoend

整個項目不需要比VS2012和NuGet包還原啓用的任何其他。

更新:我決定在NCrunch和Resharper Test Runner中都運行這兩個程序,兩者都給出相同的結果[見下圖]。

UPDATE UPDATE:我認爲它可能是XUnit,所以我試圖使用NUnit。不,仍然是同樣的問題。

Test Run from NCrunch and Resharper

**另一個更新:在控制檯將寫入按user1901853的要求。這是結果「

Test Run 2

最新:在RequestFilters越來越消滅了,我不知道爲什麼看起來這可能是一個線程問題,但我看不到的地方。 。

我APPHOST使用AppHostListenerBase

using EndToEnd.Core; 
    using Funq; 
    using Raven.Client; 
    using ServiceStack.ServiceInterface.Validation; 
    using ServiceStack.WebHost.Endpoints; 

    namespace EndToEnd 
    { 
     public class TestAppHost 
      : AppHostHttpListenerBase 
     { 
      private readonly IDocumentStore _documentStore; 

      public TestAppHost(IDocumentStore documentStore) 
       : base("Test AppHost Api", typeof(TestAppHost).Assembly) 
      { 
       _documentStore = documentStore; 
      } 

      public override void Configure(Container container) 
      { 
       ServiceStack.Text.JsConfig.EmitCamelCaseNames = true; 

       // Register RavenDB things 
       container.Register(_documentStore); 
       container.Register(c => 
       { 
        var db = c.Resolve<IDocumentStore>(); 
        return db.OpenSession(); 
       }).ReusedWithin(ReuseScope.Request); 

       Plugins.Add(new ValidationFeature()); 
       container.RegisterValidators(typeof(CreateWidgetValidator).Assembly); 

       // todo: register all of your plugins here 
       AuthConfig.Start(this, container); 
      } 
     } 
    } 

我對我所有的測試基礎測試類看起來是這樣的:

using Raven.Client; 
    using Raven.Client.Indexes; 
    using Raven.Tests.Helpers; 
    using ServiceStack.Authentication.RavenDb; 
    using ServiceStack.ServiceClient.Web; 
    using ServiceStack.ServiceInterface.Auth; 

    namespace EndToEnd 
    { 
     public abstract class ServiceStackTestBase 
      : RavenTestBase 
     { 
      protected IDocumentStore DocumentStore { get; set; } 
      protected TestAppHost Host { get; set; } 
      protected JsonServiceClient Client { get; set; } 

      protected const string ListeningOn = "http://localhost:1337/"; 

      protected string Username { get { return "testuser"; } } 
      protected string Password { get { return "password"; } } 

      protected ServiceStackTestBase() 
      { 
       DocumentStore = NewDocumentStore(); 
       IndexCreation.CreateIndexes(typeof(ServiceStackTestBase).Assembly, DocumentStore); 
       IndexCreation.CreateIndexes(typeof(RavenUserAuthRepository).Assembly, DocumentStore); 

       Host = new TestAppHost(DocumentStore); 
       Host.Init(); 
       Host.Start(ListeningOn); 

       Client = new JsonServiceClient(ListeningOn) 
       { 
        AlwaysSendBasicAuthHeader = true, 
        UserName = Username, 
        Password = Password 
       }; 

       RegisterUser(); 

       WaitForIndexing(DocumentStore); 
      } 

      private void RegisterUser() 
      { 
       Client.Send(new Registration 
       { 
        UserName = Username, 
        Password = Password, 
        DisplayName = "Test User", 
        Email = "[email protected]", 
        FirstName = "test", 
        LastName = "user" 
       }); 
      } 

      public override void Dispose() 
      { 
       DocumentStore.Dispose(); 
       Host.Dispose(); 
      } 
     } 
    } 

我的測試類是這樣的:

using System; 
    using EndToEnd.Core; 
    using FluentAssertions; 
    using ServiceStack.FluentValidation; 
    using ServiceStack.ServiceClient.Web; 
    using ServiceStack.ServiceInterface.Auth; 
    using Xunit; 

    namespace EndToEnd 
    { 
     public class RegistrationTests 
      : ServiceStackTestBase 
     { 
      [Fact] 
      public void Throws_validation_exception_when_bad_widget() 
      { 
       var validator = Host.Container.Resolve<IValidator<CreateWidget>>(); 
       validator.Should().NotBeNull(); 


       try 
       { 
        var response = Client.Post(new CreateWidget 
        { 
         Name = null 
        }); 
        // It get's here every once in a while 
        throw new Exception("Should Not Get Here!"); 
       } 
       catch (WebServiceException wex) 
       { 
        wex.StatusCode.Should().Be(400); 
        wex.ErrorMessage.Should().Be("'Name' should not be empty."); 
       } 
      } 
     } 
    } 

我的代碼查找服務是這樣的:

using System; 
    using Raven.Client; 
    using ServiceStack.FluentValidation; 
    using ServiceStack.ServiceHost; 
    using ServiceStack.ServiceInterface; 
    using ServiceStack.ServiceInterface.ServiceModel; 

    namespace EndToEnd.Core 
    { 
     [Authenticate] 
     public class WidgetsService 
      : Service 
     { 
      private readonly IDocumentSession _session; 

      public WidgetsService(IDocumentSession session) 
      { 
       _session = session; 
      } 

      public CreateWidgetResponse Post(CreateWidget input) 
      { 
       var widget = new Widget { Name = input.Name }; 
       _session.Store(widget); 
       _session.SaveChanges(); 

       return new CreateWidgetResponse { Widget = widget }; 
      } 
     } 

     [Route("/widgets", "POST")] 
     public class CreateWidget : IReturn<CreateWidgetResponse> 
     { 
      public string Name { get; set; } 
     } 

     public class CreateWidgetResponse 
     { 
      public CreateWidgetResponse() 
      { 
       ResponseStatus = new ResponseStatus(); 
      } 

      public Widget Widget { get; set; } 
      public ResponseStatus ResponseStatus { get; set; } 
     } 

     public class Widget 
     { 
      public Widget() 
      { 
       Created = DateTimeOffset.UtcNow; 
      } 

      public string Id { get; set; } 
      public string Name { get; set; } 
      public DateTimeOffset Created { get; set; } 
     } 

     public class CreateWidgetValidator : AbstractValidator<CreateWidget> 
     { 
      public CreateWidgetValidator() 
      { 
       RuleFor(m => m.Name).NotEmpty(); 
      } 
     } 
    } 
+0

克隆你的回購,可以完全複製你所說的。試圖找到一些模式。你有沒有嘗試啓用日誌?我想知道POST請求是否被緩存,因爲當你的'Throws_validation_exception_when_bad_widget'首先運行時,它會通過。當其他兩個之一運行時,它會失敗。 – 2013-03-17 15:54:25

+0

這可能是有道理的,有沒有辦法關閉緩存? – 2013-03-18 17:10:20

+0

實際上只是雙重檢查,我沒有註冊一個緩存提供程序,我記得請求過濾器「有時」被清除。 – 2013-03-18 17:18:47

回答

6

我沒有複製你的環境的能力,但運行時在VS2010中,使用.NET 4,NUnit和ReSharper Test Runner,我一直無法重現'驗證沒有解僱'的問題。我已經運行了30多次你的測試。我可以考慮驗證不會觸發的幾個原因是沒有添加插件或插件沒有註冊驗證過濾器。如果我列出的任何一個案例都是問題,下面的2 if statements可能會給你一些「內省」。希望這有些幫助。

if (!TestAppHost.Instance.Plugins.Any(x => x.GetType() == typeof(ValidationFeature))) 
{ 
    Console.Write("Validation Plugin is not added"); 
    //TestAppHost.Instance.Plugins.Add(new ValidationFeature()); 
} 

if (!TestAppHost.Instance.RequestFilters.Any(x => x.Target.ToString() == "ServiceStack.ServiceInterface.Validation.ValidationFilters")) 
{ 
    Console.Write("No validation request filter"); 
    //TestAppHost.Instance.Container.RegisterValidators(typeof(CreateWidgetValidator).Assembly); 
} 

下面是我的packages.config,所以你可以看到我們環境中的差異。

<packages> 
    <package id="FluentAssertions" version="2.0.1" targetFramework="net40" /> 
    <package id="NUnit" version="2.6.2" targetFramework="net40" /> 
    <package id="RavenDB.Client" version="2.0.2261" targetFramework="net40" /> 
    <package id="RavenDB.Database" version="2.0.2261" targetFramework="net40" /> 
    <package id="RavenDB.Embedded" version="2.0.2261" targetFramework="net40" /> 
    <package id="RavenDB.Tests.Helpers" version="2.0.2261" targetFramework="net40" /> 
    <package id="ServiceStack" version="3.9.38" targetFramework="net40-Client" /> 
    <package id="ServiceStack.Authentication.RavenDB" version="3.9.35" targetFramework="net40" /> 
    <package id="ServiceStack.Common" version="3.9.38" targetFramework="net40-Client" /> 
    <package id="ServiceStack.OrmLite.SqlServer" version="3.9.39" targetFramework="net40-Client" /> 
    <package id="ServiceStack.Redis" version="3.9.38" targetFramework="net40-Client" /> 
    <package id="ServiceStack.Text" version="3.9.38" targetFramework="net40-Client" /> 
    <package id="xunit" version="1.9.1" targetFramework="net40" /> 
</packages> 
+0

這是奇怪的部分。驗證有時會觸發,有時不會觸發。如果我單獨進行測試,每次都能正常工作。當我與其他測試一起運行時,它是失敗的時候。 – 2013-03-11 18:36:38

+0

與所有測試(30+次)一起運行時,我無法重現。上面的2條if語句(在答案中)可以幫助診斷驗證失敗的原因。 – paaschpa 2013-03-11 19:25:51

+0

嘗試添加到我的代碼中,並獲得「無驗證請求過濾器」的輸出。現在爲什麼沒有一個? https://www.ecreat.com/shard/s15/sh/9ad633bb-48d7-42b7-a98c-a211759580a4/d3384efb951c73c12803860be564beae – 2013-03-11 20:10:31