因此,我试图使用RavenDB和ServiceStack构建端到端集成测试套件,但我遇到了一个非常奇怪的问题,即验证不能在某些请求上运行。这真的很奇怪,我不确定我做错了什么。我正在使用NCrunch。测试有时会通过,有时会失败。
希望这是一个简单的修复方法,并且是我正在做的事情。
您可以在http://github.com/khalidabuhakmeh/endtoend上下载整个项目
您只需启用VS2012和NuGet包还原即可。
更新:我决定在NCrunch和Resharper Test Runner中运行这个程序,两者都得到了相同的结果,见下图。
更新更新:我认为它可能是XUnit,所以我尝试使用NUnit。不,仍然是同样的问题。
**另一个更新:根据user1901853的请求将写入放入控制台。这就是结果。“
的最新更新: 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();
}
}
}
发布于 2013-03-12 01:45:29
我没有能力复制您的环境,但当在VS2010中运行时,使用.NET 4、NUnit和ReSharper测试运行器,我无法重现您的“验证无法触发”的问题。我已经运行了你的测试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>
https://stackoverflow.com/questions/15297745
复制相似问题