【问题标题】:Mock/Stub constructor模拟/存根构造函数
【发布时间】:2011-11-24 19:49:35
【问题描述】:

我有以下代码:

class Clients
  constructor : ->
    @clients = []

  createClient : (name)->

    client = new Client name
    @clients.push client

我正在像这样使用 Jasmine BDD 对其进行测试:

describe 'Test Constructor', ->

  it 'should create a client with the name foo', ->

    clients = new clients
    clients.createClient 'Foo'
    Client.should_have_been_called_with 'Foo'

  it 'should add Foo to clients', ->

    clients = new clients
    clients.createClient 'Foo'

    expect(clients.clients[0]).toEqual SomeStub

在我的第一个测试中,我想检查是否使用正确的名称调用了构造函数。在我的第二个中,我只想确认来自新客户端的任何内容都已添加到数组中。

我正在使用 Jasmine BDD,它有一种创建间谍/模拟/存根的方法,但似乎无法测试构造函数。所以我正在寻找一种方法来测试构造函数,如果有一种方法我不需要额外的库但我对任何事情都持开放态度,那就太好了。

【问题讨论】:

    标签: javascript coffeescript jasmine


    【解决方案1】:

    我认为这里最好的计划是将新Client 对象的创建拉到一个单独的方法中。这将允许您单独测试 Clients 类并使用模拟 Client 对象。

    我已经编写了一些示例代码,但我还没有使用 Jasmine 对其进行测试。希望您能大致了解它的工作原理:

    class Clients
      constructor: (@clientFactory) ->
        @clients = []
    
      createClient : (name)->
        @clients.push @clientFactory.create name
    
    clientFactory = (name) -> new Client name
    
    describe 'Test Constructor', ->
    
      it 'should create a client with the name foo', ->
        mockClientFactory = (name) ->
        clients = new Clients mockClientFactory
    
        clients.createClient 'Foo'
    
        mockClientFactory.should_have_been_called_with 'Foo'
    
      it 'should add Foo to clients', ->
        someStub = {}
        mockClientFactory = (name) -> someStub
        clients = new Clients mockClientFactory
    
        clients.createClient 'Foo'
    
        expect(clients.clients[0]).toEqual someStub
    

    现在的基本计划是使用一个单独的函数 (clientFactory) 来创建新的 Client 对象。然后在测试中模拟这个工厂,让您可以准确控制返回的内容,并检查它是否被正确调用。

    【讨论】:

    • 我担心我不得不以这种方式解决它。尽管如此,还是很好的答案,谢谢。
    【解决方案2】:

    可以在 Jasmine 中存根构造函数,语法有点出乎意料:

    spy = spyOn(window, 'Clients');
    

    换句话说,您不会将new 方法存根,而是在类名所在的上下文中存根,在本例中为window。然后,您可以链接 andReturn() 以返回您选择的假对象,或链接 andCallThrough() 以调用真正的构造函数。

    另请参阅:Spying on a constructor using Jasmine

    【讨论】:

    • 如果 Clients 是闭包上的变量,这实际上不起作用。
    【解决方案3】:

    我的解决方案最终类似于@zpatokal

    我最终在我的应用程序(不是真正的大应用程序)中使用了一个模块,并从那里进行了模拟。一个问题是and.callThrough 不起作用,因为将从 Jasmine 方法调用构造函数,所以我不得不对and.callFake 做一些诡计。

    在 unit.coffee 上

    class PS.Unit
    

    关于units.coffee

    class PS.Units
      constructor: ->
        new PS.Unit
    

    关于规范文件:

    Unit = PS.Unit
    
    describe 'Units', ->
      it 'should create a Unit', ->
        spyOn(PS, 'Unit').and.callFake -> new Unit arguments... # and.callThrough()
        expect(PS.Unit).toHaveBeenCalled()
    

    【讨论】:

      【解决方案4】:

      使用最新 jasmine 版本的更清晰的解决方案:

      window.Client = jasmine.createSpy 'Client'
      clients.createClient 'Foo'
      expect(window.Client).toHaveBeenCalledWith 'Foo'
      

      【讨论】:

        猜你喜欢
        • 2017-05-01
        • 2019-11-24
        • 2013-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多