合约.需要抛出pex错误
本文关键字:pex 错误 合约 | 更新日期: 2023-09-27 17:54:13
可能重复:
如何配置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);
}
根据我对Pex的有限经验,我的理解是Contract
方法定义了达到它们所处方法的先决条件
Contract.Requires(!string.IsNullOrWhiteSpace(username));
您的意思是,不应该使用null或空白username参数来访问该语句。佩克斯基本上是在说你错了。这是Pex真正擅长的一件事。这意味着您有可能使用NullReferenceException
,或者在对CreateUser
方法的某些调用中没有检查空/空白的username
。那么,你的任务就是找到哪里。您可以通过处理CreateUser
方法中的空/空白username
,然后为其去掉Contract.Requires
,或者通过确保CreateUser
的所有调用方都传递一个非空、非空的用户名来解决此问题。我认为,更好的选择取决于您的情况,但在几乎所有情况下,我都会在CreateUser
方法中处理空/空白用户名。这样,您就可以在代码中的一个位置优雅地处理错误。
当然,您确实应该了解哪个调用者可以传递null或空白,因为这可能表明用户输入验证问题以及其他潜在问题。
我发现,如果您使用标准的合约重写器,请在失败时取消勾选assert,并使用类型化的Requires参数让代码通过ArgumentNullException。
contract.Requires<ArgumentNullException>(i!=null);
当您执行此操作时,方法将抛出argumentnullexceptions。。。pex和他们相处得很好。
在编译时,您仍然可以像预期的那样进行合同检查和静态检查。
看起来PexRaisedControlException的行为与你使用它的方式不一致。不过我不能说我使用了这个属性。我想从你的角度来看,我的方式是变通的;(
编辑:Pex应该生成这个测试,但测试应该抛出错误,这应该会导致测试通过。这不起作用的事实向我表明重写器不起作用,或者抛出的异常不是属性所寻找的异常类型。