我使用Lokad Shared Library 来定义业务验证规则。以下是我测试极端案例的方法(来自开源的示例):
[Test]
public void Test()
{
ShouldPass("rinat.abdullin@lokad.com", "pwd", "http://ws.lokad.com/TimeSerieS2.asmx");
ShouldPass("some@nowhere.net", "pwd", "http://127.0.0.1/TimeSerieS2.asmx");
ShouldPass("rinat.abdullin@lokad.com", "pwd", "http://sandbox-ws.lokad.com/TimeSerieS2.asmx");
ShouldFail("invalid", "pwd", "http://ws.lokad.com/TimeSerieS.asmx");
ShouldFail("rinat.abdullin@lokad.com", "pwd", "http://identity-theift.com/TimeSerieS2.asmx");
}
static void ShouldFail(string username, string pwd, string url)
{
try
{
ShouldPass(username, pwd, url);
Assert.Fail("Expected {0}", typeof (RuleException).Name);
}
catch (RuleException)
{
}
}
static void ShouldPass(string username, string pwd, string url)
{
var connection = new ServiceConnection(username, pwd, new Uri(url));
Enforce.That(connection, ApiRules.ValidConnection);
}
其中ValidConnection规则定义为:
public static void ValidConnection(ServiceConnection connection, IScope scope)
{
scope.Validate(connection.Username, "UserName", StringIs.Limited(6, 256), StringIs.ValidEmail);
scope.Validate(connection.Password, "Password", StringIs.Limited(1, 256));
scope.Validate(connection.Endpoint, "Endpoint", Endpoint);
}
static void Endpoint(Uri obj, IScope scope)
{
var local = obj.LocalPath.ToLowerInvariant();
if (local == "/timeseries.asmx")
{
scope.Error("Please, use TimeSeries2.asmx");
}
else if (local != "/timeseries2.asmx")
{
scope.Error("Unsupported local address '{0}'", local);
}
if (!obj.IsLoopback)
{
var host = obj.Host.ToLowerInvariant();
if ((host != "ws.lokad.com") && (host != "sandbox-ws.lokad.com"))
scope.Error("Unknown host '{0}'", host);
}
如果发现一些失败案例(即:添加了新的有效连接 url),则规则和测试将被更新。
可以在this article 中找到有关此模式的更多信息。一切都是开源的,所以请随意重用或提出问题。
PS:请注意,此示例复合规则(即 StringIs.ValidEmail 或 StringIs.Limited)中使用的原始规则都经过了全面测试,因此不需要过多的单元测试。