16

因此,我尝试使用 RavenDB 和 ServiceStack 构建端到端集成测试套件,但遇到了一个非常奇怪的问题,即验证无法在某些请求上运行。这真的很奇怪,我不确定我做错了什么。我正在使用 NCrunch。有时测试通过,有时失败。

希望这是一个简单的解决方法,并且我正在做一些令人头疼的事情。

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

除了启用 VS2012 和 NuGet 包还原之外,您不需要任何其他东西。

更新:我决定在 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<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 = "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<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();
            }
        }
    }
4

1 回答 1

6

我无法复制您的环境,但在 VS2010 中运行时,使用 .NET 4、NUnit 和 ReSharper Test Runner 我无法重现您的“验证未触发”问题。我已经运行了你的测试 30 多次。我认为验证未触发的几个原因是未添加插件或插件未注册验证过滤器。if statements如果我列出的任何一个案例都是问题,下面的 2可能会给你一些“内省”。希望这有点帮助。

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>
于 2013-03-11T17:45:29.130 回答