C# 契约。需要抛出pex错误

C# 契约。需要抛出pex错误,c#,c#-4.0,code-contracts,pex,C#,C# 4.0,Code Contracts,Pex,可能重复: 目前,当我运行pex探索时,我在类中创建的代码契约在pex探索结果中被视为错误。我认为当您使用代码契约运行pex探索时,契约失败应该被视为预期行为。 下面是导致异常的代码 试验方法: [PexMethod] public void TestEquality(Guid userId, string username, string password, string securityQuestion, string securityAnswer) { UserSecurity

可能重复:

目前,当我运行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,
               };
}

根据我对Pex有限的经验,我的理解是,
合同
方法定义了达到其所用方法的先决条件。所以,当你说

Contract.Requires(!string.IsNullOrWhiteSpace(username));
您的意思是,不应该使用null或空格username参数访问该语句。Pex基本上是说你错了。这是Pex真正有好处的一件事。这意味着您可能会出现
NullReferenceException
,或者您在调用
CreateUser
方法时没有检查空/空白
用户名
。那么,你的任务就是找到你的位置。您可以通过在
CreateUser
方法中处理null/whitespace
username
来解决此问题,然后取消该
契约。它需要
,或者通过确保
CreateUser
的所有调用方传递一个非null、非空的用户名。我认为更好的选择取决于您的情况,但在几乎所有情况下,我都会在
CreateUser
方法中处理空/空白用户名。这样,您就可以在代码中的一个位置优雅地处理错误


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

我发现,如果您使用标准契约重写器,请取消选中assert on failure,并通过使用类型化Requires参数让代码通过ArgumentNullException

contract.Requires<ArgumentNullException>(i!=null);
contract.Requires(i!=null);
执行此操作时,这些方法将抛出ArgumentNullException。。。pex与他们相处得非常好

在编译时,您仍然可以像预期的那样进行契约检查和静态检查

看起来PexRaisedContractException与您的使用方式不符。但我不能说我使用了这个属性。我想从你的角度来看,我的方式是一种变通;)


编辑:Pex应该生成这个测试,但是测试应该抛出错误,这应该会导致测试通过。这不起作用的事实向我表明,重写器不起作用,或者抛出的异常不是属性所寻找的异常类型。

PEX团队甚至监控过这个论坛吗?或者没有更多的PEX团队?我不会称之为“PEX论坛”,即使“他们”的人可能会在这里查看。看起来是论坛,我想他们不会再回复了。在pex主页上,他们注意到论坛已移至stackoverflow。Ups,应该多加注意。当然,在旧论坛上甚至有一篇关于向SO迁移的帖子。对不起,一切都好!我甚至找不到他们的旧论坛,所以谢谢你。:)这对于代码契约来说是正确的。但是,当您使用PEX执行参数化单元测试时,它应该将代码契约视为预期行为。因此,即使契约会在运行时抛出异常,pex也会按预期处理该异常。这是pex单元测试的情况。“我认为这可能是一个和探索结果有关的错误。”约书亚·戴尔(Joshua Dale)见第10-11页。“执行运行时契约检查”的设置是什么?目标项目的契约是打开的(我还为测试项目启用了它以确保)。此外,我目前收到一个ContractException,因此启用了代码契约。我强烈建议不要在CreateUser中处理null/空格。如果没有有效信息,该方法无法执行其任务,并且无论如何都需要抛出异常-这正是定义前置条件的理想情况。@Morten Mertner我不确定你在说什么。为什么我不在该方法中放置一个先决条件呢?当使用代码契约和pex时,pex将契约失败作为预期的异常使用,并在探索中标记为绿色。您的修复确实有效,但同时使用pex和代码契约并没有任何好处。“使用pex和契约并没有任何好处”这是胡说八道。以我目前的方式使用这两种技术是我在代码质量方面有史以来最大的进步。对于那些无法让它发挥作用的人来说,这是一种相当教条的说法。即使你的意思是额外的好处,我仍然不同意,因为契约给了我编译时检查,而pex给了我一个伟大的探索性测试工具。我厌倦了为空写测试…对不起。我并不是故意轻视你的修复方案,它很好用。我只是说它的行为不像过去了。而且获得支持的问题比pex团队过去更大。完全同意支持部分;)我花了一段时间让人们相信pex没有死。。。但是,由于对代码契约的静态检查有额外的要求,难怪这种东西很难销售。这是一个缺乏透明度的伟大产品。我听说Moles正在阻止pex的更新。但我不记得是在哪里听到的。
contract.Requires<ArgumentNullException>(i!=null);