2015-04-22 116 views
2

我試圖測試一個間諜將被稱爲承諾的.then塊,但塊done似乎並未執行在所有。摩卡 - 測試承諾,`完成`永遠不會被調用在承諾

我越來越timeout of 2000ms exceeded.

這裏是我測試(異步):

/** 
* Passed down to the LoginForm component to 
* handle form submission. 
*/ 
_submitHandler(data) { 
    return function(evt) { 
    evt.preventDefault && evt.preventDefault(); 
    evt.stopPropagation && evt.stopPropagation(); 

    return request('post', 'auth', data) 
     .then((res) => { 
     AuthActions.login(); 
     return res; 
     }) 
    } 
} 

這裏是我的測試:

describe('when it succeeds',() => { 
    it('should login', (done) => { 
    sinon.spy(AuthActions, 'login'); 

    Instance._submitHandler({})({}) 
     .then((res) => { 
     console.log('Called!!!'); 
     expect(AuthActions.login.called).to.equal(true); 
     AuthActions.login.restore(); 
     done(); 
     }, done); 
    }); 
}); 

我使用噶運行我的測試;柴和詩乃。

+0

你會得到什麼失敗的消息? – Bergi

回答

1

幾小時後我終於解決了這個問題。看起來then塊沒有被調用,因爲由於xhr而引發異常。

讓我詳細說明。我用興農FakeXMLHttpRequest,就像這樣:

var requests, xhr; 
beforeEach(() => { 
    requests = []; 
    xhr = sinon.useFakeXMLHttpRequest(); 
    xhr.onCreate = (req) => { 
    req.setResponseHeaders({ /* */ }); 
    requests.push(req); 
    } 
}); 

通過將一個console.logcatch塊,我發現我越來越錯誤是INVALID_STATE_ERR EXCEPTION 0。這讓我得出結論,xhr一直是問題。

然後我發現了約sinonfakeServer,並用它來代替(但我不認爲這實際上是解決這個問題的方法)。不是真的有關,但我還用​​這裏是因爲從寫無數的.restore爲存根救了我,等

describe('when it succeeds',() => { 
    var sandbox, server, Instance; 
    beforeEach(() => { 
    sandbox = sinon.sandbox.create(); 
    sandbox.useFakeServer(); 
    server = sandbox.server; 
    server.respondWith([200, { "Content-Type": "application/json" }, JSON.stringify({ data: { token: '' }})]); 
    sandbox.spy(AuthActions, 'login'); 
    Instance = TestUtils.renderIntoDocument(<Component />); 
    }); 
    afterEach(() => { 
    sandbox.restore(); 
    }); 
    it('should login', (done) => { 
    Instance._submitHandler({})({}) 
     .then(() => { 
     expect(AuthActions.login.called).to.equal(true); 
     done(); 
     }, done); 

    setTimeout(() => { 
     server.respond(); 
    }, 0); 
    }); 
}); 
2

我也有這個問題,原因是想給XHR迴應打開連接之前, ,例如

此代碼將拋出INVALID_STATE_ERR - 0FakeXMLHttpRequest.setResponseHeaders

describe("get", function() { 

    beforeEach(function() { 
    this.xhr = sinon.useFakeXMLHttpRequest(); 
    this.xhr.onCreate = function (request) { 
     request.respond(200, null, ""); 
    }; 
    }); 

    afterEach(function() { 
    this.xhr.restore(); 
    }); 

    it("should make a request", function() { 
    myObject.get("testurl"); 
    }); 

}); 

此代碼:

describe("get", function() { 

    beforeEach(function() { 
    this.xhr = sinon.useFakeXMLHttpRequest(); 
    this.requests = []; 
    this.xhr.onCreate = function (request) { 
     this.requests.push(request); 
    }; 
    }); 

    afterEach(function() { 
    this.xhr.restore(); 
    }); 

    it("should make a request", function() { 
    myObject.get("testurl"); 
    this.requests[0].respond(200, null, ""); 
    }); 

}); 

閱讀該文檔,它本身確實顯示出推到一個請求陣列相同的技術,我有下意識地,不準確地得出了這樣的印象,儘管它的名字是onCreate,更像是「應要求」。

myObject.get = function (url) { 
    var http = new XMLHttpRequest(); 
    // the XHR instance exists 
    // readyState is 0 
    // onCreate runs now 
    http.open("GET", url); 
    http.send(); 
    // readyState is 1 
    // can call setResponseHeaders and respond 
} 

的結果是,你必須把你的響應代碼調用運行XMLHttpRequestsend的方法,如後:

myObject.get("testurl"); 
this.requests[0].respond(200, null, ""); 

我用的是respond方法,但相同的是對於setResponseHeadersrespond調用setResponseHeaders)爲真 - 在您的測試中,它被稱爲太早。