ServiceStackvalidation并不总是被激活

所以我试图用RavenDB和ServiceStack构建一个End To End集成测试套件,但是我遇到了一个非常奇怪的问题,即validation不能在某些请求上运行。 这真的很奇怪,我不确定我做错了什么。 我正在使用NCrunch。 有时测试通过,有时它会失败。

希望这是一个简单的解决方案,我正在做的事情。

您可以在http://github.com/khalidabuhakmeh/endtoend上下载整个项目

除了VS2012和NuGet Package Restore之外,您不需要任何其他function。

更新:我决定在NCrunch和Resharper Test Runner中运行它,两者都给出相同的结果[见下图]。

更新更新:我认为它可能是XUnit,所以我尝试使用NUnit。 不是仍然是同样的问题。

从NCrunch和Resharper试运行

**另一个更新:根据user1901853的请求输入控制台写入。 这就是结果。“

试运行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(); 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 = "test@test.com", 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>(); 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 { 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 { public CreateWidgetValidator() { RuleFor(m => m.Name).NotEmpty(); } } } 

我无法复制您的环境,但在VS2010中运行时,使用.NET 4,NUnit和ReSharper Test Runner我无法重现您的“validation未触发”问题。 我已经运行了30多次测试。 我可以想到的一个原因是validation没有触发将没有添加插件或插件没有注册validationfilter。 if statements我列出的任何一个案例都是问题,下面的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,因此您可以看到我们环境中的差异。