ServiceStack验证并不总是射击 [英] ServiceStack Validation Not Always Firing
问题描述
所以,我想建立一个端到端的集成测试套件与RavenDB和ServiceStack,但我遇到了一个很奇怪的问题,即对不上的一些要求运行。这真的很奇怪,我不知道我做错了。我使用NCrunch。有时,测试通过,有时会失败。
希望这是一个简单的办法和一些骨头为首的我在干什么。
您也可以下载整个项目在 http://github.com/khalidabuhakmeh/endtoend
您不需要任何其他的不是VS2012和的NuGet包还原功能。
更新:我决定在这两个NCrunch和ReSharper的测试运行器运行此两者给予同样的结果[见下图]
。更新来更新:我想这可能是的xUnit,所以我试图用NUnit的。都能跟得上仍然是同样的问题。
**另一个更新:将在控制台中写道按user1901853的要求。这是的结果。
最新更新:在RequestFilters越来越消灭了,我不知道为什么。看起来这可能是一个线程问题,但我看不到的地方。
我的APPHOST使用AppHostListenerBase。
使用EndToEnd.Core;
使用Funq;
使用Raven.Client;
使用ServiceStack.ServiceInterface.Validation;
使用ServiceStack.WebHost.Endpoints;
命名空间端到端
{
公共类TestAppHost
:AppHostHttpListenerBase
{
私人只读IDocumentStore _documentStore;
公共TestAppHost(IDocumentStore文档库)
:基地(测试APPHOST阿比的typeof(TestAppHost).Assembly)
{
_documentStore =文档库;
}
公众覆盖无效配置(集装箱货柜)
{
ServiceStack.Text.JsConfig.EmitCamelCaseNames = TRUE;
//注册RavenDB的东西
container.Register(_documentStore);
container.Register(C =>
{
变种DB = c.Resolve< IDocumentStore>();
返回db.OpenSession();
})ReusedWithin(ReuseScope.Request)。
Plugins.Add(新ValidationFeature());
container.RegisterValidators(typeof运算(CreateWidgetValidator).Assembly);
// TODO:注册所有插件这里
AuthConfig.Start(这一点,容器);
}
}
}
我的基础测试类的所有我的测试是这样的:
使用Raven.Client;
使用Raven.Client.Indexes;
使用Raven.Tests.Helpers;
使用ServiceStack.Authentication.RavenDb;
使用ServiceStack.ServiceClient.Web;
使用ServiceStack.ServiceInterface.Auth;
命名空间端到端
{
公共抽象类ServiceStackTestBase
:RavenTestBase
{
保护IDocumentStore文档库{获得;组; }
保护TestAppHost主机{获得;组; }
保护JsonServiceClient客户端{获得;组; }
受保护的常量字符串ListeningOn =HTTP://本地主机:1337 /;
受保护的字符串用户名{{返回testuser的; }}
受保护的字符串密码{{返回密码; }}
保护ServiceStackTestBase()
{
文档库= NewDocumentStore();
IndexCreation.CreateIndexes(typeof运算(ServiceStackTestBase).Assembly,文档库);
IndexCreation.CreateIndexes(typeof运算(RavenUserAuthRepository).Assembly,文档库);
主机=新TestAppHost(文档库);
Host.Init();
Host.Start(ListeningOn);
客户端=新JsonServiceClient(ListeningOn)
{
AlwaysSendBasicAuthHeader = TRUE,
用户名=用户名,
密码=密码
};
RegisterUser();
WaitForIndexing(文档库);
}
私人无效RegisterUser()
{
Client.Send(新注册
{
用户名=用户名,
密码=密码,
显示名称=测试用户,
电子邮件=test@test.com
名字=测试,
姓氏=用户
});
}
公众覆盖无效的Dispose()
{
DocumentStore.Dispose();
Host.Dispose();
}
}
}
我的测试类看起来是这样的:
使用系统;
使用EndToEnd.Core;
使用FluentAssertions;
使用ServiceStack.FluentValidation;
使用ServiceStack.ServiceClient.Web;
使用ServiceStack.ServiceInterface.Auth;
使用的xUnit;
命名空间端到端
{
公共类RegistrationTests
:ServiceStackTestBase
{
[事实]
公共无效Throws_validation_exception_when_bad_widget()
{
VAR验证= Host.Container.Resolve< IValidator< CreateWidget>>();
validator.Should()NotBeNull()。
尝试
{
VAR响应= Client.Post(新CreateWidget
{
NAME =空
});
//它在一段时间获得的这里的每一次
抛出新的异常(不应该到这里来!);
}
赶上(WebServiceException WEX)
{
。wex.Status code.Should()成为(400);
wex.ErrorMessage.Should()被('名称'不能为空);
}
}
}
}
我的code看起来像这样的服务:
使用系统;
使用Raven.Client;
使用ServiceStack.FluentValidation;
使用ServiceStack.ServiceHost;
使用ServiceStack.ServiceInterface;
使用ServiceStack.ServiceInterface.ServiceModel;
命名空间EndToEnd.Core
{
[认证]
公共类WidgetsService
: 服务
{
私人只读IDocumentSession _session;
公共WidgetsService(IDocumentSession会话)
{
_session =会议;
}
公共CreateWidgetResponse帖子(CreateWidget输入)
{
VAR部件=新的Widget {名称= input.Name};
_session.Store(小工具);
_session.SaveChanges();
返回新CreateWidgetResponse {=的Widget小部件};
}
}
[路线(/小工具,POST)
公共类CreateWidget:IReturn< CreateWidgetResponse>
{
公共字符串名称{;组; }
}
公共类CreateWidgetResponse
{
公共CreateWidgetResponse()
{
ResponseStatus =新ResponseStatus();
}
公众的Widget控件{获得;组; }
公共ResponseStatus ResponseStatus {获得;组; }
}
公共类小工具
{
公共小工具()
{
创建= DateTimeOffset.UtcNow;
}
公共字符串ID {获得;组; }
公共字符串名称{;组; }
公众的DateTimeOffset创建{获得;组; }
}
公共类CreateWidgetValidator:AbstractValidator< CreateWidget>
{
公共CreateWidgetValidator()
{
RuleFor(米=> m.Name).NotEmpty();
}
}
}
我没有复制你的环境的能力,但在运行时VS2010使用.NET 4的NUnit和ReSharper的测试运行我一直没能重现你的验证不点火的问题。我已经运行测试30+次。一对夫妇的原因,我能想到的验证不费一枪将没有添加插件或插件不注册验证过滤器。在2 if语句
下面可能会给你一些反思,如果任一所列案件的问题。希望这是有点帮助的。
如果(TestAppHost.Instance.Plugins.Any(X =>!x.GetType()== typeof运算(ValidationFeature)))
{
Console.Write(验证插件不会添加);
//TestAppHost.Instance.Plugins.Add(new ValidationFeature());
}
如果(TestAppHost.Instance.RequestFilters.Any(X =>!x.Target.ToString()==ServiceStack.ServiceInterface.Validation.ValidationFilters))
{
Console.Write(无验证请求过滤器);
//TestAppHost.Instance.Container.RegisterValidators(typeof(CreateWidgetValidator).Assembly);
}
下面是我的packages.config所以你可以看到在我们的环境中的差异。
<包装>
<包ID =FluentAssertions版本=2.0.1targetFramework =net40/>
<包ID =NUnit的版本=2.6.2targetFramework =net40/>
<包ID =RavenDB.Client版本=2.0.2261targetFramework =net40/>
<包ID =RavenDB.Database版本=2.0.2261targetFramework =net40/>
<包ID =RavenDB.Embedded版本=2.0.2261targetFramework =net40/>
<包ID =RavenDB.Tests.Helpers版本=2.0.2261targetFramework =net40/>
<包ID =ServiceStack版本=38年3月9日targetFramework =net40客户/>
<包ID =ServiceStack.Authentication.RavenDB版本=35年3月9日targetFramework =net40/>
<包ID =ServiceStack.Common版本=38年3月9日targetFramework =net40客户/>
<包ID =ServiceStack.OrmLite.SqlServer版本=39年3月9日targetFramework =net40客户/>
<包ID =ServiceStack.Redis版本=38年3月9日targetFramework =net40客户/>
<包ID =ServiceStack.Text版本=38年3月9日targetFramework =net40客户/>
<包ID =xUnit的版本=1.9.1targetFramework =net40/>
< /包>
So I was trying to build a End To End integration testing suite with RavenDB and ServiceStack but I ran into a really weird issue where the validation doesn't run on some requests. This is really strange and I am not sure what I am doing wrong. I am using NCrunch. Sometimes the test passes, sometimes it fails.
Hope this is an easy fix and something bone headed I'm doing.
You can download the whole project on http://github.com/khalidabuhakmeh/endtoend
You don't need anything other than VS2012 and NuGet Package Restore enabled.
UPDATE: I decided to run this in both NCrunch and Resharper Test Runner and both give the same result [see image below].
UPDATE UPDATE: I thought it could be XUnit, so I tried to use NUnit. Nope still the same problem.
**Another Update: Put in console writes as per user1901853's request. This was the result."
Latest Update: the RequestFilters are getting wiped out and I'm not sure why. It seems like it could be a threading issue, but I can't see where.
My AppHost is using 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);
}
}
}
My base test class for all of my tests looks like this:
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();
}
}
}
my test class looks like this:
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.");
}
}
}
}
My code looks like this for the service:
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();
}
}
}
I don't have the ability to duplicate your environment but while running in VS2010, using .NET 4, NUnit and ReSharper Test Runner I have not been able to reproduce your issue of 'Validation not firing'. I have run your tests 30+ times. A couple of reasons I can think of Validation not firing would be not having the plugin added or the plugin not registering the validation filters. The 2 if statements
below might give you some 'introspection' if either of the cases I listed are the issue. Hope this is somewhat helpful.
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);
}
Below is my packages.config so you can see the differences in our environments.
<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>
这篇关于ServiceStack验证并不总是射击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!