模拟/存根构造函数
Posted
技术标签:
【中文标题】模拟/存根构造函数【英文标题】: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,它有一种创建间谍/模拟/存根的方法,但似乎无法测试构造函数。所以我正在寻找一种方法来测试构造函数,如果有一种方法我不需要额外的库但我对任何事情都持开放态度,那就太好了。
【问题讨论】:
【参考方案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'
【讨论】:
以上是关于模拟/存根构造函数的主要内容,如果未能解决你的问题,请参考以下文章