Тесты NUnit отказываются запускаться из-за исключения StackOverflowException - PullRequest
0 голосов
/ 05 октября 2018

Я вообще не уверен, что здесь вызывает исключение.

У меня было несколько тестов, использующих 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;
            }
        }

1 Ответ

0 голосов
/ 05 октября 2018

Причиной исключения StackOverflowException было наличие Properties в классе Address, который случайно делал рекурсивные обращения к себе.Это не было проблемой с 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...