2015-02-24 22 views
2

我想在使用AutoFixture的單元測試中使用約定。我有如圖所示的密碼值對象:如何在AutoFixture中創建一個樣本生成器來始終返回一個匹配正則表達式的字符串?

public class Password : SemanticType<string> 
{ 
    private int _daysPasswordValid; 

    public Password(string password) : base(IsValid, password) 
    { 
     Guard.NotNullOrEmpty(() => password, password); 
     Guard.IsValid(() => password, password, IsValid, "Invalid Password"); 

     DateCreated = DateTime.Now; 
    } 

    static bool IsValid(string candidate) 
    { 
     //password cannot contain be whitespace 
     if (string.IsNullOrWhiteSpace(candidate)) 
      return false; 

     const string passwordPattern = @"^(?=.*[A-Z].*[A-Z])(?=.*[[email protected]#$&=()-*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{20}$"; 

     var match = Regex.Match(candidate, passwordPattern); 

     return match.Success; 
    } 

    public DateTime DateCreated { get; private set; } 

    public int DaysPasswordValid 
    { 
     get { return _daysPasswordValid; } 
     set 
     { 
      const int minimunDays = 0; 
      const int maximumDays = 90; 

      if (value <= maximumDays && value > minimunDays) 
       _daysPasswordValid = value; 
      else 
       throw new ArgumentOutOfRangeException(
        "Password must be valid more than {0} and no more than {1} days.".Fmt(minimunDays, maximumDays)); 
     } 
    } 

    public static implicit operator string(Password password) 
    { 
     return password.Value; 
    } 

    public static explicit operator Password(string value) 
    { 
     return new Password(value); 
    } 
} 

我希望能夠基於密碼類創建一個夾具和有一個有效的密碼創建的夾具,換句話說,相匹配的密碼RegEx模式在密碼類中。我一直在尋找AutoFixture中可用的RegularExpressionGenerator,但還沒有完全掌握。這裏是製造商迄今:

public class ValidPasswordBuilder : ISpecimenBuilder 
{ 
    public ValidPasswordBuilder(string regularExpressionRequest) 
    { 
     PasswordRegularExpression = regularExpressionRequest; 
    } 

    public string PasswordRegularExpression { get; private set; } 

    public object Create(object request, ISpecimenContext context) 
    { 
     var pi = request as ParameterInfo; 
     if (pi != null && pi.Name == "password" && pi.ParameterType == typeof(string)) 
     { 
      var generator = new RegularExpressionGenerator(); 
      var regExRequest = new RegularExpressionRequest(PasswordRegularExpression); 
      var result = generator.Create(regExRequest, context); 
      return result.ToString(); 
     } 

     return new NoSpecimen(request); 
    } 
} 

下面是測試:

[Fact] 
    public void ValidPasswordMatches() 
    { 
     var fixture = new Fixture(); 
     fixture.Customizations.Add(new ValidPasswordBuilder(PasswordPattern)); 
     Action a =() => fixture.Create<Password>(); 
     a.ShouldNotThrow<ArgumentException>(); 
    } 

我可以運行測試的設置上面,並把它傳遞,但如果我調試它,我得到一個錯誤在密碼類(通過保護條款)的IsValid的功能,指出從製造商返回的密碼是:

Ploeh.AutoFixture.Kernel.NoSpecimen

我似乎從未得到與RegEx模式匹配的結果。我覺得我很接近,但需要一些幫助克服駝峯。

謝謝!

回答

4

因爲它看起來像,您使用模式不支持:

^(?=.*[A-Z].*[A-Z])(?=.*[[email protected]#$&=()-*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{20}$ 

Regular expression visualization

用不同的正則表達式嘗試。

編輯:或者嘗試做thisthis,爲了配置AutoFixture使用不同的正則表達式,而不改變Password類。


AutoFixture通過施加dk.brics.automaton算法變爲正則表達式到Automatons

您可以使用不同的模式或使用不同的引擎將正則表達式轉換爲自動機。作爲一個例子,你可以使用Rex引擎。

雖然,即使雷克斯不支持正則表達式,如下面的結構目前不支持雷克斯:

錨\ G,\ B,\ B,命名組,前瞻,回顧後,原樣少數次的量詞,反向引用,條件替換,替換。


如果你想嘗試雷克斯與AutoFixture您可以使用以下生成:

internal class RexRegularExpressionGenerator : ISpecimenBuilder 
{ 
    public object Create(object request, ISpecimenContext context) 
    { 
     if (request == null) 
      return new NoSpecimen(); 

     var regularExpressionRequest = request as RegularExpressionRequest; 
     if (regularExpressionRequest == null) 
      return new NoSpecimen(); 

     var pattern = regularExpressionRequest.Pattern; 

     try 
     { 
      var regex = RexEngine 
       .GenerateMembers(
        new RexSettings(pattern) { k = 1 }) 
       .FirstOrDefault(); 

      if (Regex.IsMatch(regex, pattern)) 
       return regex; 
     } 
     catch (ArgumentException) 
     { 
      return new NoSpecimen(request); 
     } 

     return new NoSpecimen(request); 
    } 
} 

據我所知,你可以下載雷克斯只能作爲.NET應用程序(。exe文件),然後您可以像引用其他任何託管程序集一樣引用它。

+1

這對我來說很好,因爲我對OoTB RegularExpressionGenerator創建的字符串不滿意(「\ d」似乎總是創建一個「0」)。 Rex.exe被編譯爲x86,因此我使用dotpeek 10反編譯並重新構建爲DLL並使用上述Generator,並且令人驚歎:\ d將生成不止0-9,包括泰米爾語和各種時髦的unicode數字。 (使我們將\ d的正則表達式從\ d明確地更改爲[0-9] – 2015-11-06 14:01:48

+0

非常好!這很好理解:) – 2015-11-06 14:07:33

相關問題