2

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

最后 3 个进行 id 测试的测试也是如此。我必须使用“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 方法,然后测试它们。

4

2 回答 2

3

在下面 matyr 的评论后编辑:我最初认为这是由于new操作员的古怪,因为有几个测试使用 syntax new Foo().bar。但是,new在这些情况下,行为与 Pickels 预期的一样。因此,尽管此答案不是所述问题的解决方案,但为了后代,这里有一个评论:

当你写

new A().B

您正在引用BA实例的属性。

但是如果你写

new A.B()

(或者只是new A.B-CoffeeScript 隐式在目标末尾添加括号,new如果它们不存在)那么您正在创建A.B. 这变得相当混乱——什么是new A().B()?——因为new运算符有自己的特殊优先规则。因此,我建议使用括号来阐明此类代码,例如

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

这里曾讨论过试图在 CoffeeScript 中使这种行为更直观,但经过大力的努力,最终确定“治疗比疾病更糟糕”。

于 2011-03-05T19:46:42.667 回答
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'''(假设您希望允许空字符串作为名称),因为放错or位置而不是?,或if name代替if name?,可能会导致''与长度> 0 的字符串的行为不同。

测试#3

expect( () -> new Node() ).toThrow()

这个测试失败了,因为() -> new Node()定义了一个函数——一个永远不会运行的函数。我想你的意思是写new Node()

其他想法

查看Speks文档,听起来首选样式是使用beforeEach. 当然,这在您测试构造函数本身时不起作用,但您可能希望在将来的大部分测试中使用它。

这是您的测试套件的重写版本,其中包含所有这些建议并将测试分为三种类型:创建异常的测试、预期正常行为的测试以及对象应该正常运行但属于边缘情况的测试:

node_spec = describe 'Node', () ->

  # exception tests
  it 'should throw an error if there are no arguments', () ->
      expect( new Node() ).toThrow()

  it 'should throw an error if there is only one argument', () ->
      expect( new Node('foo') ).toThrow()

  # normal tests
  node = new Node('foo', 1)

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

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

  # slightly unusual case of id = 0, name = '' (convertible to false)
  node = new Node('', 0)

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

  it 'should have an empty string as its name', () ->
      expect( node.name ).toEqual('')
于 2011-03-06T03:48:14.750 回答