不确定如何使用 FluentValidation 测试此 .NET 字符串
Not sure how to test this .NET string with FluentValidation
REF: A .NET Fiddle 的(基本上)代码,如下。
我正在尝试使用 FluentValidation 测试 string
是否有效 Uri
:
public class LinksValidator : AbstractValidator<string>
{
public LinksValidator()
{
RuleFor(x => x)
.Must(LinkMustBeAUri)
.WithMessage("Link '{PropertyValue}' must be a valid URI. eg: http://www.SomeWebSite.com.au");
}
private static bool LinkMustBeAUri(string link)
{
if (string.IsNullOrWhiteSpace(link))
{
return false;
}
Uri result;
return Uri.TryCreate(link, UriKind.Absolute, out result);
}
}
以及验证测试...
public class LinksValidatorTests
{
private readonly LinksValidator _linksValidator;
public LinksValidatorTests()
{
_linksValidator = new LinksValidator();
}
[Theory]
[InlineData("Http://www.SomeDomain.com")]
[InlineData("https://www.SomeDomain.com")]
[InlineData("http://www.SomeDomain.com.au")]
public void GivenAValidUri_Validate_ShouldNotHaveAValidationError(string uri)
{
// Arrange.
// Act & Assert.
_linksValidator.ShouldNotHaveValidationErrorFor(l => l, uri);
}
}
但是该测试方法的最后一行没有编译:
如何向编译器提供提示以告诉它使用哪种方法?
所以,这是不可能的,因为它位于您无法修改的库中。参见 here。
但是,有一个解决方法。这是为了确保通用参数不相同。
这是工作代码:
public static void Main()
{
Console.WriteLine("Hello World");
var uri = "Http://www.SomeDomain.com";
var linksValidator = new LinksValidator();
linksValidator.ShouldNotHaveValidationErrorFor(uri);
}
public class LinksValidator : AbstractValidator<LinksValidator.UrlWrapper>
{
public class UrlWrapper { public string Url { get; set; } }
public LinksValidator()
{
RuleFor(x => x.Url)
.Must(LinkMustBeAUri)
.WithMessage("Link '{PropertyValue}' must be a valid URI. eg: http://www.SomeWebSite.com.au");
}
//Optional 'overload' since l => l.Url seems to be superfluous
public void ShouldNotHaveValidationErrorFor(string uri)
{
this.ShouldNotHaveValidationErrorFor(l => l.Url, uri);
}
private static bool LinkMustBeAUri(string link)
{
if (string.IsNullOrWhiteSpace(link))
{
return false;
}
//Courtesy of @Pure.Krome's comment and
Uri outUri;
return Uri.TryCreate(link, UriKind.Absolute, out outUri)
&& (outUri.Scheme == Uri.UriSchemeHttp || outUri.Scheme == Uri.UriSchemeHttps);
}
}
我不太熟悉 FluentValidation 库的工作原理 - 所以可能有更简洁的方法来包装这个 hack
另请注意,我更改了您检测 Uri
字符串的方式。 TryCreate
对几乎任何字符串都将 return 为真(我无法找到它曾经为假的情况)。
我是这样写的(所以可以重复使用):
public static class Validations
{
public static IRuleBuilderOptions<T, string> Url<T>(this IRuleBuilder<T, string> ruleBuilder)
{
bool UrlIsValidUri(string url) => Uri.TryCreate(url, UriKind.Absolute, out var outUri)
&& (outUri.Scheme == Uri.UriSchemeHttp || outUri.Scheme == Uri.UriSchemeHttps);
return ruleBuilder.Must(UrlIsValidUri);
}
}
和 use/test 就像这样(使用 xUnit):
public class ValidationsTest
{
[Theory]
[InlineData("google.com", false)]
[InlineData("https://google.com", true)]
public void UrlValidationWorks(string url, bool expectedIsValid)
{
var entity = new TestEntity
{
Url = url
};
var validator = new TestEntityValidator();
var result = validator.Validate(entity);
Assert.Equal(expectedIsValid, result.IsValid);
}
private class TestEntity
{
public string Url { get; set; }
}
private class TestEntityValidator : AbstractValidator<TestEntity>
{
public TestEntityValidator()
{
RuleFor(x => x.Url).Url();
}
}
}
REF: A .NET Fiddle 的(基本上)代码,如下。
我正在尝试使用 FluentValidation 测试 string
是否有效 Uri
:
public class LinksValidator : AbstractValidator<string>
{
public LinksValidator()
{
RuleFor(x => x)
.Must(LinkMustBeAUri)
.WithMessage("Link '{PropertyValue}' must be a valid URI. eg: http://www.SomeWebSite.com.au");
}
private static bool LinkMustBeAUri(string link)
{
if (string.IsNullOrWhiteSpace(link))
{
return false;
}
Uri result;
return Uri.TryCreate(link, UriKind.Absolute, out result);
}
}
以及验证测试...
public class LinksValidatorTests
{
private readonly LinksValidator _linksValidator;
public LinksValidatorTests()
{
_linksValidator = new LinksValidator();
}
[Theory]
[InlineData("Http://www.SomeDomain.com")]
[InlineData("https://www.SomeDomain.com")]
[InlineData("http://www.SomeDomain.com.au")]
public void GivenAValidUri_Validate_ShouldNotHaveAValidationError(string uri)
{
// Arrange.
// Act & Assert.
_linksValidator.ShouldNotHaveValidationErrorFor(l => l, uri);
}
}
但是该测试方法的最后一行没有编译:
如何向编译器提供提示以告诉它使用哪种方法?
所以,这是不可能的,因为它位于您无法修改的库中。参见 here。
但是,有一个解决方法。这是为了确保通用参数不相同。
这是工作代码:
public static void Main()
{
Console.WriteLine("Hello World");
var uri = "Http://www.SomeDomain.com";
var linksValidator = new LinksValidator();
linksValidator.ShouldNotHaveValidationErrorFor(uri);
}
public class LinksValidator : AbstractValidator<LinksValidator.UrlWrapper>
{
public class UrlWrapper { public string Url { get; set; } }
public LinksValidator()
{
RuleFor(x => x.Url)
.Must(LinkMustBeAUri)
.WithMessage("Link '{PropertyValue}' must be a valid URI. eg: http://www.SomeWebSite.com.au");
}
//Optional 'overload' since l => l.Url seems to be superfluous
public void ShouldNotHaveValidationErrorFor(string uri)
{
this.ShouldNotHaveValidationErrorFor(l => l.Url, uri);
}
private static bool LinkMustBeAUri(string link)
{
if (string.IsNullOrWhiteSpace(link))
{
return false;
}
//Courtesy of @Pure.Krome's comment and
Uri outUri;
return Uri.TryCreate(link, UriKind.Absolute, out outUri)
&& (outUri.Scheme == Uri.UriSchemeHttp || outUri.Scheme == Uri.UriSchemeHttps);
}
}
我不太熟悉 FluentValidation 库的工作原理 - 所以可能有更简洁的方法来包装这个 hack
另请注意,我更改了您检测 Uri
字符串的方式。 TryCreate
对几乎任何字符串都将 return 为真(我无法找到它曾经为假的情况)。
我是这样写的(所以可以重复使用):
public static class Validations
{
public static IRuleBuilderOptions<T, string> Url<T>(this IRuleBuilder<T, string> ruleBuilder)
{
bool UrlIsValidUri(string url) => Uri.TryCreate(url, UriKind.Absolute, out var outUri)
&& (outUri.Scheme == Uri.UriSchemeHttp || outUri.Scheme == Uri.UriSchemeHttps);
return ruleBuilder.Must(UrlIsValidUri);
}
}
和 use/test 就像这样(使用 xUnit):
public class ValidationsTest
{
[Theory]
[InlineData("google.com", false)]
[InlineData("https://google.com", true)]
public void UrlValidationWorks(string url, bool expectedIsValid)
{
var entity = new TestEntity
{
Url = url
};
var validator = new TestEntityValidator();
var result = validator.Validate(entity);
Assert.Equal(expectedIsValid, result.IsValid);
}
private class TestEntity
{
public string Url { get; set; }
}
private class TestEntityValidator : AbstractValidator<TestEntity>
{
public TestEntityValidator()
{
RuleFor(x => x.Url).Url();
}
}
}