Contract.Requires抛出pex错误

可能重复:
如何配置Pex以尊重代码合同?

目前,当我运行pex探索时,我在我的类中创建的代码契约被视为pex探索结果中的错误。 我认为当你使用代码合同进行pex勘探时,合同失败应该被视为预期的行为。 这是导致exception的代码。

测试方法:

[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() != 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); } 

根据我对Pex的有限经验,我的理解是Contract方法定义了达到它们所处方法的先决条件。所以,当你说

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

你是说无法使用null或空白用户名参数来达到该语句。 Pex基本上说你错了。 这是Pex 真正有用的一件事。 这意味着您可能会遇到NullReferenceException或者您在CreateUser方法的某些调用中没有检查空/空白username 。 那么,你的任务就是找到哪里。 您可以通过在CreateUser方法中处理null / whitespace username ,然后删除Contract.Requires ,或者确保CreateUser所有调用者都传递非null,非空用户名来解决问题。 我认为更好的选择取决于你的情况,但几乎在所有情况下,我都会在CreateUser方法中处理null / whitespace用户名。 这样,您可以在代码中的某个位置正常处理错误。

当然,您确实应该看到哪个调用者可以传递null或空格,因为这可能表示用户输入validation问题,以及其他潜在问题。

我发现如果你使用标准的合同重写器,在失败时取消断言断言并使用类型化的Requires参数让你的代码穿过ArgumentNullException。

 contract.Requires(i!=null); 

当你这样做时,方法将抛出argumentnullexceptions … pex与它们表现得非常好。

在编译时,您仍然可以按预期进行合同检查和静态检查。

它看起来像PexRaisedContractException并不像你如何使用它。 我不能说我使用那个属性。 我想从你的角度来看,我的方式是一种解决方法;)

编辑:Pex应该生成此测试,但测试应该抛出错误,这应该导致测试通过。 这不起作用的事实告诉我,重写器不工作或抛出的exception不是属性正在寻找的exception类型。