2

私は次の機能を持っています:

function getPersonData(id) {
  retrieveData(
    id,
    function(person) {
      if(person.name) {
        displayPerson(person);
      }
    }
}

function retrieveData(id, successCallBack) {
    executeRequest(id, {
      success: successCallBack
    });
}

getPersonDataID に基づいて個人の情報を取得します。次にretrieveData、id と successCallBack 関数を渡して呼び出します。

retrieveDataid と successCallBackexecuteRequestを受け取り、データを取得して person オブジェクトを返す別の関数 を呼び出します。

私はテストしようとしgetPersonDataており、次の仕様を設定しています

describe("when getPersonData is called with the right person id", function() {
  beforeEach(function() {
    spyOn(projA.data, "retrieveData").and.returnValue(
      {
        'name': 'john'
      }
    );
    spyOn(projA.data, "displayPerson");
    projA.data.getPersonData("123");
  });

  it("displays the person's details", function() {
    expect(projA.data.displayPerson).toHaveBeenCalled();
  );
}); 

しかし、仕様が実行されると、displayPersonメソッドは呼び出されません。これは、結果を返すようにモックしたにもかかわらず、成功した callBack から返された個人データが渡さfunction(person)れていないretrieveDataためです。

私の質問は: これは callBack 関数をテストする正しい方法ですか? いずれにせよ、私は何が間違っていますか?

4

1 に答える 1

3

わかりました、ジャスミンは多くの微妙な点でトリッキーであり、コードには2つの主な問題があると思います

  1. 相互にラップされた非同期呼び出しが多すぎます。それ自体は問題ではありませんが、JASMINE でのテストが非常に難しくなります。たとえば、まったく同じパラメーターを使用して関数retrieveDataを呼び出すだけの関数を持つことのポイントは何executeRequestですか。ただし、方法はわずかに異なります。

getPersonData を次のように書き直しました

function getPersonData(id) {
  // this is needed to properly spy in Jasmine
  var self = this;

  //replaced retrieveData with just execute request
  // self is required to properly spy in Jasmine
  self.executeRequest(id, {
    success: function(person) {
     if (person.name) {
      self.displayPerson(person);
     }
    }
  })
}

//I don't know what exactly executeRequest does 
//but I took the liberty to just make it up for this example 
function executeRequest(id, callback) {
 callback.success({
   name: id
  });
}

//I also assumed that projA would look something like this
var projA = {
 data: {
  getPersonData: getPersonData,
  retrieveData: retrieveData,
  displayPerson: displayPerson,
  executeRequest: executeRequest
 }
};

done2. Jasmine で非同期コードをテストするには、テストにコールバックを含める必要があります。また、コールバック関数が自動的に起動することが予想される場合は、関数内で設定する必要がありますsetTimeout。そうしないと、コールバック関数は起動しません。調整された例を次に示します。

    describe("when getPersonData is called with the right person id",  function() {
     beforeEach(function() {
      //you should not spyOn retriveData or executeCode because it will override the function you wrote and will never call displayPerson

      // you should only have spies on the methods you are testing otherwise they will override other methods
      spyOn(projA.data, "displayPerson");
     });

     it("displays the person's details", function(done) {
      // it's better to call the function within specific test blocks so you have control over the test
      projA.data.getPersonData("123");

      // at this point, it will just have called the getPersonData but will not call executeRequest
      setTimeout(function() {
       //this block will just call executeRequest
       setTimeout(function() {
        //this block will finally call displayPerson
        expect(projA.data.displayPerson).toHaveBeenCalled();

        //tell jasmine the test is done after this
        done();
        })
       })
     });
    })
于 2016-05-03T20:15:04.910 に答える