测试:参数输入验证

时间:2011-03-05 19:08:39

标签: javascript coffeescript

在下面的代码中,我想知道是否可以调整进行名称检查的测试。因为一旦我添加了检查ID不能为null的代码,我的前3个测试就会失败。

进行id测试的最后3个测试也是如此。我必须使用'foo'作为名称,否则这些测试也会失败。不确定是否也没问题?

要测试的代码:

class Error

class Node
    constructor: (name, id) ->
        if not name?
            throw new Error('Name cannot be null')

        @name = name

        if not id?
            throw new Error('Id cannot be null')

        @id = id

window.Node = Node

规范:

node_spec = describe 'Node', () ->

    it 'should have the name foo', () ->
        expect( new Node('foo').name ).toEqual('foo')

    it 'should have the name bar', () ->
        expect( new Node('bar').name ).toEqual('bar')

    it 'should throw an error if the name is null', () ->
        expect( () -> new Node() ).toThrow()

    it 'should have an id of 0', () ->
        expect( new Node('foo', 0).id ).toEqual(0)

    it 'should have an of 1', () ->
        expect( new Node('foo', 1).id ).toEqual(1)

    it 'should throw an error if id is null', () ->
        expect( new Node('foo') ).toThrow()

window.node_spec = node_spec

更新 我想一个解决方案是为id和name设置一个getter和setter方法,然后测试它们。

2 个答案:

答案 0 :(得分:3)

在matyr的评论下面编辑:我最初认为这是由于new运算符的怪癖,因为有几个测试使用了语法new Foo().bar 。但是,new表现为Pickels在这种情况下的预期。因此,尽管这个答案是所述问题的解决方案,但这是为了后人的审查:

写作时

new A().B

您正在引用新B实例的A属性。

但如果你写

new A.B()

(或仅new A.B - CoffeeScript会在new目标末尾隐含地添加括号(如果它们不存在),那么您正在创建A.B的新实例。这很令人困惑 - 什么是new A().B()? - 因为new运算符有自己的特殊优先级规则。所以,我建议使用括号来澄清这些代码,例如

(new A).B
new (A.B)

在CoffeeScript中尝试使这种行为更直观有discussion here,但经过精力充沛的努力,确定“治愈比疾病更糟糕。”

答案 1 :(得分:1)

让我再试一次:现在,你有三个失败的测试。让我们弄清楚如何解决每个失败。

测试#1

expect( new Node('foo').name ).toEqual('foo')

由于缺少id,因此收到错误。我会继续测试那个错误,

expect( new Node('foo') ).toThrow()

并重写测试#1以声明一个合法的,无错误的Node实例,就像使用id测试行一样:

expect( new Node('foo', 1).name ).toEqual('foo')

这没什么不对。每次测试非错误行为时,都应该正确实例化;在这种情况下,这意味着传递名称和ID。

测试#2

expect( new Node('bar').name ).toEqual('bar')

这与测试#1基本相同。事实上,我说你实际上在这里测试得太彻底了。您应该问的问题是:我是否有理由相信将'bar'作为名称而不是'foo'会产生不同的行为?我会说“不。”

因此,我要么彻底删除'bar'测试,要么将'bar'替换为''(假设您要允许空字符串作为名称),因为错位{{1而不是or,或?而不是if name,可能导致if name?的行为与长度为>的字符串不同。 0

测试#3

''

此测试失败,因为expect( () -> new Node() ).toThrow() 定义了一个函数 - 一个永不运行的函数。我认为你的意思是只改写() -> new Node()

其他想法

查看Speks文档,听起来像是使用new Node()重复实例声明代码的首选样式。当然,当您测试构造函数本身时,这将不起作用,但您可能希望将来将其用于大部分测试。

这是一个包含所有这些建议的测试套件的重写版本,并将测试分为三种类型:创建异常的那些,预期正常行为的那些,以及应该表现得很好但是边缘情况:

beforeEach