Using Sinon.js and preventing a call to my app ser

2019-06-26 01:29发布

问题:

Simple enough question:

I want us sinon.js to test a piece of javascript to ensure that it calls the $.ajax method while doing two things:

  1. I don't want to actually hit the server
  2. I want to mock up a response from the server

so here's the JS:

  $.ajax
    url: "/tickets/id.json"
    dataType: 'json'

  .done (data) =>
    HandlebarsTemplates["tickets/popup_title"] data

and here's my test:

describe 'PopupDisplayer', ->

  beforeEach ->
    loadFixtures 'popup_displayer'
    new PopupDisplayer

    @title_stub = sinon.stub( HandlebarsTemplates, "tickets/popup_title")

    @jquery_stub = sinon.stub(jQuery, 'ajax').yieldsTo('done', {})

    //This triggers the ajax call
    $('.popupable .title').mouseenter()

  afterEach ->
    HandlebarsTemplates['tickets/popup_title'].restore()
    HandlebarsTemplates['tickets/popup_content'].restore()

    jQuery.ajax.restore()

    @server.restore()

  it 'renders the title with the data returned from the server', ->
    expect(@title_stub).toHaveBeenCalledWith( {})  

This test failed though with the following exception:

TypeError: ajax expected to yield to 'done', but no object with such a property was passed. Received [[object Object]]

So I guess I'm wondering if I can mock up an jQuery request to get a response that can successfully respond to the .done call apparently I don't understand the defferedObject() well enough.

回答1:

To mock the server's response you want to stub the return value of $.ajax:

  ...
  @jquery_stub = sinon.stub(jQuery, 'ajax').returns
    done: (callback) -> callback {...} # your object here
  ...

Note that this only stubs the done callback. If you want to test other behaviours you will probably need to implement other handlers (fail, then etc.).

You could also return an actual jQuery Deferred object:

  ...    
  @deferred = new jQuery.Deferred
  @jquery_stub = sinon.stub(jQuery, 'ajax').returns(deferred)
  ...

In this case you will have to explicitly trigger the returned Deferred before doing your tests:

  ...    
  @deferred.resolveWith(null, [{}]) # your object here
  ...