mardi 24 février 2015

How do I create a specimen builder in AutoFixture to always return a string that matches a Regex?

I am trying to use conventions in my unit tests which make use of AutoFixture. I have a Password value object as shown:



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])(?=.*[!@#$&=()-*])(?=.*[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);
}
}


I would like to be able to create a fixture based on the Password class and have the fixture created with a valid password, in other words, a password that matches the RegEx pattern in the Password class. I have been looking at the RegularExpressionGenerator available in AutoFixture but haven't quite gotten things to work. Here is the builder have so far:



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


Here is the test:



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


I can run the test as setup above, and it passes, but if I debug it, I get an error in the IsValid function in the Password class (through the Guard clause) that says that the password returned from the builder is:



Ploeh.AutoFixture.Kernel.NoSpecimen



I never seem to get a result that matches the RegEx pattern. I feel like I'm close, but need some help getting over the hump.


Thanks!


Aucun commentaire:

Enregistrer un commentaire