【问题标题】:Not sure how to test this .NET string with FluentValidation不确定如何使用 FluentValidation 测试此 .NET 字符串
【发布时间】:2016-08-02 09:57:27
【问题描述】:

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);
    }
}

但该测试方法的最后一行没有编译:

如何向编译器提供提示以告诉它使用哪种方法?

【问题讨论】:

  • 没有办法,因为你的类型是同一个字符串,字符串。您将不得不使用不同的技术,以便您的 lambda 不是 l => l。我对此几乎没有经验,但我从未见过有人在没有检查过属性的情况下使用它。 l => l.blah

标签: c# .net fluentvalidation


【解决方案1】:

因此,这是不可能的,因为它位于您无法修改的库中。见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 https://stackoverflow.com/a/25654227/563532
        Uri outUri;
        return Uri.TryCreate(link, UriKind.Absolute, out outUri)
               && (outUri.Scheme == Uri.UriSchemeHttp || outUri.Scheme == Uri.UriSchemeHttps);
    }
}

我不太熟悉 FluentValidation 库的工作原理 - 所以可能有一种更简洁的方法来包装这个 hack

另外请注意,我更改了您检测Uri 字符串的方式。 TryCreate 几乎会为任何字符串返回 true(我无法找到它曾经为 false 的情况)。

【讨论】:

  • 回复:TryCreate 和真与假。将其更改为UriKind.Absolute
  • 还有@rob ..检查这个好方法来检查字符串uri是否合法:stackoverflow.com/a/25654227/30674
  • @Pure.Krome 不错的发现 :) 我已将其编辑为带有归属的答案
【解决方案2】:

我是这样写的(所以它可以重复使用):

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);
    }
}

并像这样使用/测试它(使用 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();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    相关资源
    最近更新 更多