我不确定是什么原因导致了异常。
我有许多使用NUnit TestCases的测试,并且这些测试运行良好,没有问题。然后,我编写了一个额外的测试,除了几个变量值外,它几乎与其他测试完全相同,现在由于StackOverflowException,我的测试都无法运行。
[05/10/2018 10:10:00 Informational] ------ Run test started ------
[05/10/2018 10:10:00 Informational] NUnit Adapter 3.10.0.21: Test execution started
[05/10/2018 10:10:00 Informational] Running all tests in C:\test.dll
[05/10/2018 10:10:00 Informational] NUnit3TestExecutor converted 9 of 9 NUnit test cases
[05/10/2018 10:10:04 Error] The active test run was aborted. Reason: Process is terminated due to StackOverflowException.
[05/10/2018 10:10:04 Informational] ========== Run test finished: 0 run (0:00:04.661362) ==========
另一个测试类中的测试将运行,但是即使我注释掉其他测试,该类中的任何测试也不会运行。
从下面的代码中可以看到,除了将变量名作为参数和测试用例传递外,大多数测试在结构上都与其他测试相同。
[TestFixture]
class FluentAddressValidatorTest
{
private FluentAddressValidator validator;
[OneTimeSetUp]
public void Setup()
{
validator = new FluentAddressValidator();
}
[Test]
public void FluentAddressValidatorAllowsValidAddressObject()
{
//Arrange
FluentAddressValidator validator = new FluentAddressValidator();
Address address = new Address();
address = new Address
{
HouseNum = "1",
HouseName = "Big House",
StreetName = "Street",
Locality = "Locality",
Town = "Town",
County = "County",
Postcode = "NE11NM"
};
//Act
ValidationResult result = validator.Validate(address);
//Assert
Assert.That(result.IsValid, Is.True);
}
[TestCase("1$")]
[TestCase("1.")]
[TestCase("32A.")]
[TestCase("1 ")]
public void FluentAddressValidatorDisallowsInvalidHouseNumber(string houseNum)
{
Address address = new Address
{
HouseNum = houseNum,
HouseName = "House name",
StreetName = "Street",
Locality = "Locality",
Town = "Town",
County = "County",
Postcode = "NE11NM"
};
validator.ShouldHaveValidationErrorFor(a => a.HouseNum, address);
}
[TestCase("House.Name")]
[TestCase("House name.")]
[TestCase("Housè")]
[TestCase("")]
[TestCase(" ")]
[TestCase("House name House name House name House name House name")]
public void FluentAddressValidatorDisallowsInvalidHouseName(string houseName)
{
Address address = new Address
{
HouseNum = "1a",
HouseName = houseName,
StreetName = "Street",
Locality = "Locality",
Town = "Town",
County = "County",
Postcode = "NE11NM"
};
validator.ShouldHaveValidationErrorFor(a => a.HouseName, address);
}
[TestCase("Street.Name")]
[TestCase("Street name.")]
[TestCase("Strèet")]
[TestCase("")]
[TestCase(" ")]
[TestCase("Street name Street name Street name Street name Street name")]
public void FluentAddressValidatorDisallowsInvalidStreetName(string streetName)
{
Address address = new Address
{
HouseNum = "1a",
HouseName = "house",
StreetName = streetName,
Locality = "Locality",
Town = "Town",
County = "County",
Postcode = "NE11NM"
};
validator.ShouldHaveValidationErrorFor(a => a.StreetName, address);
}
[TestCase("'Locality'")]
[TestCase("Locality.")]
[TestCase("Lòcality")]
[TestCase("")]
[TestCase(" ")]
[TestCase("Locality Locality Locality Locality Locality Locality ")]
public void FluentAddressValidatorDisallowsInvalidLocality(string locality)
{
Address address = new Address
{
HouseNum = "1a",
HouseName = "house",
StreetName = "Street name",
Locality = locality,
Town = "Town",
County = "County",
Postcode = "NE11NM"
};
validator.ShouldHaveValidationErrorFor(a => a.Locality, address);
}
[TestCase("'Town'")]
[TestCase("Town.")]
[TestCase("Tòwn")]
[TestCase("")]
[TestCase(" ")]
[TestCase("Town Town Town Town Town Town Town Town Town Town")]
public void FluentAddressValidatorDisallowsInvalidTown(string town)
{
Address address = new Address
{
HouseNum = "1a",
HouseName = "house",
StreetName = "Street name",
Locality = "Locality",
Town = town,
County = "County",
Postcode = "NE11NM"
};
validator.ShouldHaveValidationErrorFor(a => a.Town, address);
}
[TestCase("'County'")]
[TestCase("County.")]
[TestCase("Còunty")]
[TestCase("")]
[TestCase(" ")]
[TestCase("County County County County County County")]
public void FluentAddressValidatorDisallowsInvalidCounty(string county)
{
Address address = new Address
{
HouseNum = "1a",
HouseName = "house",
StreetName = "Street name",
Locality = "Locality",
Town = "Town",
County = county,
Postcode = "NE11NM"
};
validator.ShouldHaveValidationErrorFor(a => a.County, address);
}
[TestCase("'Postc0de'")]
[TestCase("Ne11111.")]
[TestCase("NXXXX12")]
[TestCase("NXXXX!£2")]
[TestCase("")]
[TestCase(" ")]
[TestCase("NE1 1BN")]
public void FluentAddressValidatorDisallowsInvalidPostcode(string postcode)
{
Address address = new Address
{
HouseNum = "1a",
HouseName = "house",
StreetName = "Street name",
Locality = "Locality",
Town = "Town",
County = "County",
Postcode = postcode
};
validator.ShouldHaveValidationErrorFor(a => a.Postcode, address);
}
}
FluentAddressValidator
public class FluentAddressValidator : AbstractValidator<Address>
{
private readonly string alphanumericalSpaceCaseInsensitiveRegex = "^[a-zA-Z0-9 ]*$";
private readonly string alphabeticalSpaceCaseInsensitiveRegex = "^[a-zA-Z ]*$";
public FluentAddressValidator()
{
RuleFor(a => a.HouseNum).NotEmpty().MaximumLength(8).Matches(alphanumericalSpaceCaseInsensitiveRegex) //Not empty string, alphanumeric, allows spaces
.WithMessage("House number must be alphanumerical only.");
RuleFor(a => a.HouseName).NotEmpty().MaximumLength(32).Matches(alphabeticalSpaceCaseInsensitiveRegex) //Not empty string, alphabetical, includes spaces
.WithMessage("House name must be alphabetical only.");
RuleFor(a => a.StreetName).NotEmpty().MaximumLength(32).Matches(alphabeticalSpaceCaseInsensitiveRegex) //Not empty string, alphabetical, includes spaces
.WithMessage("Street name must be alphabetical only.");
RuleFor(a => a.Locality).NotEmpty().MaximumLength(32).Matches(alphabeticalSpaceCaseInsensitiveRegex) //Not empty string, alphabetical, includes spaces
.WithMessage("Locality must be alphabetical only.");
RuleFor(a => a.Town).NotEmpty().MaximumLength(32).Matches(alphabeticalSpaceCaseInsensitiveRegex) //Not empty string, alphabetical, includes spaces
.WithMessage("Town must be alphabetical only.");
RuleFor(a => a.County).NotEmpty().MaximumLength(32).Matches(alphabeticalSpaceCaseInsensitiveRegex) //Not empty string, alphabetical, includes spaces
.WithMessage("County must be alphabetical only.");
RuleFor(a => a.Postcode).NotEmpty().MaximumLength(16).Must(Common.IsValidUkPostcode) //Not empty string, is valid uk postcode
.WithMessage("Postcode must follow valid UK postcode format.");
}
}
IsValidUkPostcode
public static bool IsValidUkPostcode(string postcode)
{
postcode = postcode.Replace(" ", string.Empty);
postcode = postcode.ToUpper();
Regex r = new Regex(@"([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\s?[0-9][A-Za-z]{2})");
if (r.IsMatch(postcode))
{
return true;
}
else
{
return false;
}
}
答案 0 :(得分:4)
引起StackOverflowException的原因是由于Address类中存在Properties,从而意外地递归地对其自身进行了调用。这与FluentValidation或NUnit无关。
例如:
public string Street
{
get
{
return Street;
}
set
{
Street = value;
}
}
这将导致递归,并最终将导致堆栈溢出。为防止这种情况,请设置一个私有后备字段,该属性可以将数据委托给该字段。
private string street;
public string Street
{
get
{
return this.street;
}
set
{
this.street = value;
}
}