如何在使用FsCheck属性属性时排除空值?

时间:2016-12-07 16:24:58

标签: tdd xunit.net fscheck

我需要编写一个接收参数的简单方法(例如string)并执行smth。通常我最终会进行两次测试。第一个是guard clause。第二个将验证预期的行为(为简单起见,该方法不应该失败):

[Fact]
public void DoSmth_WithNull_Throws()
{
    var sut = new Sut();
    Assert.Throws<ArgumentNullException>(() =>
        sut.DoSmth(null));
}

[Fact]
public void DoSmth_WithValidString_DoesNotThrow()
{
    var s = "123";
    var sut = new Sut();
    sut.DoSmth(s); // does not throw
}

public class Sut
{
    public void DoSmth(string s)
    {
        if (s == null)
            throw new ArgumentNullException();

        // do smth important here
    }
}

当我尝试使用FsCheck [Property]属性生成随机数据时,null和许多其他随机值会传递给测试,这会在某些时候导致NRE:

[Property]
public void DoSmth_WithValidString_DoesNotThrow(string s)
{
    var sut = new Sut();
    sut.DoSmth(s); // throws ArgumentNullException after 'x' tests
}

我意识到这就是FsCheck产生大量随机数据以涵盖不同情况的全部想法,这绝对是非常好的。

是否有任何优雅的方法来配置[Property]属性以排除不受欢迎的值? (在这个null)的特定测试中。

1 个答案:

答案 0 :(得分:2)

FsCheck有一些内置类型可用于指示特定行为,例如,引用类型值不应为null。其中之一是NonNull<'a>。如果你要求其中一个,而不是要求一个原始字符串,你将得到没有空值。

在F#中,您可以将其解构为函数参数:

[<Property>]
let DoSmth_WithValidString_DoesNotThrow (NonNull s) = // s is already a string here...
    let sut = Sut ()
    sut.DoSmth s // Use your favourite assertion library here...
}

我认为在C#中,应该看起来像这样,但我没有尝试过:

[Property]
public void DoSmth_WithValidString_DoesNotThrow(NonNull<string> s)
{
    var sut = new Sut();
    sut.DoSmth(s.Get); // throws ArgumentNullException after 'x' tests
}