10

ジャスミンでクリックされた要素でイベントハンドラーが呼び出されることをテストしようとしています。クリックされるDOM要素「PadElement」を含む「Pad」オブジェクトを用意します。イベント ハンドラーは、Pad オブジェクトのメソッドです。

GRAPH.Pad = function(graphDiv, graph) {
    this.graph = graph;

    this.clickHandler = function(e) {
        console.log('padElement clickHandler called');
        //this.graph.createVertex(e.clientX, e.clientY);
    };
    this.padElement = GRAPH.padElement(graphDiv, this.clickHandler);
}

GRAPH.padElement = function(graphDiv, clickHandler) {
    //Initialize pad
    var NS="http://www.w3.org/2000/svg";
    var pad=document.createElementNS(NS,"svg");
    pad.setAttributeNS(null, 'id', 'pad');
    graphDiv.appendChild(pad);
    pad.addEventListener('click', clickHandler)
    return pad;
}

ジャスミンテスト:

var testDiv = document.createElement('div');
var testGraph = new GRAPH.Graph(testDiv);
var testPad = new GRAPH.Pad(testDiv, testGraph);

  it('has its clickHandler function called when its padElement is clicked',
    function() {
      spyOn(testPad, "clickHandler");
      simulateClick(testPad.padElement);
      //testPad.clickHandler();
      expect(testPad.clickHandler).toHaveBeenCalled();
  });

ただし、テストは失敗します。イベントリスナーが呼び出されることに注意してください(console.logはマウスクリックとsimulateClickで正常に書き込みます)、そしてtestPad.clickHandler()を直接呼び出すと、ジャスミンのスパイがそれを拾うことができます. しかし、実際のテストではどうなるでしょうか。イベント ハンドラーの呼び出しは、実行時に別のオブジェクトに転送されますか? これを行う正しい方法は何ですか?

4

2 に答える 2

6

によって呼び出されるのではなくGRAPH.padElement、提供された を呼び出すことを実際にテストしています。私がそれを行う方法はclickHandlerthis.clickHandlerGRAPH.PadGRAPH.padElement

var testDiv = document.createElement('div');
var clickHandlerSpy = jasmine.CreateSpy();
var padelement = padElement(testDiv , clickHandlerSpy);

  it('has its clickHandler function called when its padElement is clicked',
    function() {
      simulateClick(testPad.padElement);
      expect(clickHandlerSpy).toHaveBeenCalled();
  });

これは、達成しようとしているものとは少し異なるように聞こえるかもしれません。しかし、理想的な単体テストの世界では、各ユニットを個別にテストする必要があるため、最初にpadElement(上記のように) 本来の動作をテストし、次に別のテストを記述して、GRAPH.Pad正しいハンドラーが に渡されていることを確認しpadElementます。padElementこれを行うには、内部から直接作成するのではGRAPH.Padなく、何らかの方法で外部から注入し、jasmine 仕様でモックします。この部分が明確でない場合はお知らせください。いくつかのコードをまとめることができます。

于 2012-05-02T14:37:14.600 に答える
3

より一般的な説明を追加するには:

関数をイベント リスナーとしてアタッチする前に、スパイする必要があります

いくつかの擬似コード:

it("succeeds", function(){
  var o = {}
  o.f = function() { console.log("event caught!");} //your eventHandler
  spyOn(o, "f").and.callThrough(); //o.f is now a spy
  addEventListener('click', o.f); //spy listens for event 

  fireEvent("click"); //"event caught!" is written to console

  expect(o.f).toHaveBeenCalled(); //success, we're happy
});



it("fails", function(){
  var o = {}
  o.f = function() { console.log("event caught!");} //your eventHandler
  addEventListener('click', o.f); //your eventHandler function listens for event
  spyOn(o, "f").and.callThrough(); //o.f is now a spy

  fireEvent("click"); //"event caught!" is written to console

  expect(o.f).toHaveBeenCalled(); //fail, we waste a couple of hours not understanding why
});

したがって、ハンドラーが呼び出されていることがわかっているが、スパイが登録されていない.tohaveBeenCalled()場合は、最初に何が起こるかを確認してください: あなたのスパイまたはリスナーの割り当て。スパイが最初に来る必要があります。

于 2016-09-08T13:40:58.153 に答える