Подтвердить что ты не робот

Contract.Requires бросает ошибки pex

Возможный дубликат:
Как настроить Pex для соблюдения кодовых контрактов?

В настоящее время, когда я запускаю pex-исследование, кодовые контракты, созданные мной в моих классах, рассматриваются как ошибки в результатах исследования pex. Я подумал, что когда вы проводили pex-разведку с использованием кодовых контрактов, сбой в контрактах должен рассматриваться как ожидаемое поведение. Вот код, вызывающий исключения.

Метод тестирования:

[PexMethod]
public void TestEquality(Guid userId, string username, string password, string securityQuestion, string securityAnswer)
{
    UserSecurity user = UserTools.CreateUser(Guid.NewGuid(), username, password, securityQuestion, securityAnswer);

    bool passwordResult = UserTools.VerifyInput(password, user.Password, user.PasswordSalt);
    bool securityAnswerResult = UserTools.VerifyInput(securityAnswer, user.SecurityAnswer, user.SecurityAnswerSalt);

    Assert.IsTrue(passwordResult, "Password did not correctly re-hash");
    Assert.IsTrue(securityAnswerResult, "Security Answer did not correctly re-hash");
}

Вызов метода отказа:

public static UserSecurity CreateUser(Guid userId, string username, string password, string securityQuestion, string securityAnswer)
{
    Contract.Requires(userId != Guid.Empty);
    Contract.Requires(!string.IsNullOrWhiteSpace(username));
    Contract.Requires(!string.IsNullOrWhiteSpace(password));
    Contract.Requires(!string.IsNullOrWhiteSpace(securityQuestion));
    Contract.Requires(!string.IsNullOrWhiteSpace(securityAnswer));
    Contract.Ensures(Contract.Result<UserSecurity>() != null);

    byte[] passwordSalt;
    byte[] securityAnswerSalt;

    return new UserSecurity
               {
                   UserId = userId,
                   Username = username,
                   Password = SecurityUtilities.GenerateHash(password, out passwordSalt),
                   PasswordSalt = passwordSalt,
                   SecurityQuestion = securityQuestion,
                   SecurityAnswer = SecurityUtilities.GenerateHash(securityAnswer, out securityAnswerSalt),
                   SecurityAnswerSalt = securityAnswerSalt,
               };
}

--- Описание

failing test: ContractException, Precondition failed: !string.IsNullOrWhiteSpace(username)

Guid s0
   = new Guid(default(int), (short)32, (short)32, default(byte), default(byte), 
              default(byte), default(byte), default(byte), 
              default(byte), default(byte), default(byte));
this.TestEquality(s0, (string)null, (string)null, (string)null, (string)null);


[TestMethod]
[PexGeneratedBy(typeof(HashTests))]
[PexRaisedContractException]
public void TestEqualityThrowsContractException173()
{
    Guid s0
       = new Guid(default(int), (short)32, (short)32, default(byte), default(byte), 
                  default(byte), default(byte), default(byte), 
                  default(byte), default(byte), default(byte));
    this.TestEquality(s0, (string)null, (string)null, (string)null, (string)null);
}
4b9b3361

Ответ 1

Мое понимание, из моего ограниченного опыта работы с Pex, заключается в том, что методы Contract определяют предпосылки для достижения метода, в котором они находятся. Итак, когда вы говорите

Contract.Requires(!string.IsNullOrWhiteSpace(username));

вы говорите, что не должно быть никакого способа, чтобы этот оператор мог быть достигнут с помощью параметра имени пользователя null или whitespace. Pex в основном говорит, что вы ошибаетесь. Это одна вещь, для которой Pex действительно хорош. Это означает, что у вас есть потенциал для NullReferenceException или вы не проверяете пустое/пустое пространство username в некотором обращении к вашему методу CreateUser. Тогда ваша задача - найти где. Вы можете исправить проблему, обратившись к null/whitespace username в методе CreateUser, затем избавившись от Contract.Requires для него или гарантируя, что все вызывающие абоненты CreateUser передают ненулевой, - пустое имя пользователя. Я думаю, лучший выбор зависит от вашей ситуации, но почти во всех случаях я бы обработал имя пользователя null/whitespace в методе CreateUser. Таким образом, вы можете обрабатывать ошибку изящно в одном месте в своем коде.

Конечно, вы действительно должны видеть, какой вызывающий может передать пустое или пустое пространство, поскольку это может указывать на проблему проверки ввода пользователя, среди других потенциальных проблем.

Ответ 2

Я нахожу, что если вы используете стандартный перезаписывающий контракт, отключайте утверждение при ошибке и пусть ваш код thron ArgumentNullException с помощью типизированного аргумента Requires.

contract.Requires<ArgumentNullException>(i!=null);

когда вы это сделаете, методы будут генерировать аргумент nullexceptions... pex отлично себя ведет с ними.

Во время компиляции вы все равно получаете проверку контрактов и статическую проверку, как и следовало ожидать.

Похоже, что PexRaisedContractException не ведет себя с тем, как вы его используете. Я не могу сказать, что я использую этот атрибут. Думаю, с вашей точки зрения мой путь - это работа вокруг;)

EDIT: Pex должен сгенерировать этот тест, но тест должен выдать ошибку, и это должно привести к прохождению теста. факт, что это не работает, подсказывает мне, что переписывающий не работает или что созданное исключение не является типом исключения, который ищет атрибут.