簡體   English   中英

ES6合作者的模擬構建

[英]Mock construction of es6 collaborator

我有一個利用助手類的類,我想驗證它是否正確構造了那些對象。 因此,我試圖在類中添加“構造函數”方法,但是顯然我做的不正確:

"use strict";

class Collaborator {
  constructor(settings) {
    console.log("Don't want this to be called!")
    this.settings = settings;
  }
}

class ThingToTest {
  constructor(settings) {
    this.helper = new Collaborator(settings);
  }
}

const assert = require("assert");
const sinon = require("sinon");

describe("ThingToTest", () => {
  let settings = "all the things"

  context("spying on constructor", () => {
    let spy = sinon.spy(Collaborator, "constructor")
    after(() => spy.restore()) 
    describe("constructor", () => {
      it("creates a Collaborator with provided settings", () => {
        new ThingToTest(settings);
        sinon.assert.calledWith(spy, settings)
      })
    })
  })

  context("spying on prototype constructor", () => {
    let spy = sinon.spy(Collaborator.prototype, "constructor")
    after(() => spy.restore()) 
    describe("constructor", () => {
      it("creates a Collaborator with provided settings", () => {
        new ThingToTest(settings);
        sinon.assert.calledWith(spy, settings)
      })
    })
  })

  context("stub constructor", () => {
    before(() => {
      sinon.stub(Collaborator, "constructor", (settings) => {
        console.log("This should be called so we can inspect", settings);
      })
    })
    after(() => { Collaborator.constructor.restore() }) 
    describe("constructor", () => {
      it("creates a Collaborator with provided settings", () => {
        new ThingToTest(settings);
      })
    })
  })

  context("stub prototype constructor", () => {
    before(() => {
      sinon.stub(Collaborator.prototype, "constructor", (settings) => {
        console.log("This should be called so we can inspect", settings);
      })
    })
    after(() => { Collaborator.prototype.constructor.restore() }) 
    describe("constructor", () => {
      it("creates a Collaborator with provided settings", () => {
        new ThingToTest(settings);
      })
    })
  })

})

運行此操作將產生以下(不希望的)結果:

ThingToTest
    spying on constructor
      constructor
Don't want this to be called!
        1) creates a Collaborator with provided settings
    spying on prototype constructor
      constructor
Don't want this to be called!
        2) creates a Collaborator with provided settings
    stub constructor
      constructor
Don't want this to be called!
        ✓ creates a Collaborator with provided settings
    stub prototype constructor
      constructor
Don't want this to be called!
        ✓ creates a Collaborator with provided settings

似乎存根是某種工作方式,因為將存根測試放在間諜測試之前,就用可怕的“ TypeError:試圖包裝已經包裝的構造函數”來測試錯誤。 因此,清楚地弄清楚如何模擬Collaborators構造函數只是我做錯的事情的一半。 我也沒有正確恢復構造函數。 有什么建議么?

不是我想要的解決方案,但是暫時我可能最終會使用它(但是,如果您有建議,請把我從我自己身上救出來):

context("checking Collaborator in a more integration style test", () => {
    describe("constructor", () => {
      it("creates a Collaborator with provided settings", () => {
        let thing = new ThingToTest(settings);
        assert.equal(thing.helper.settings, settings)
      })
    })
  })

這樣可以通過並驗證協作者是否設置了正確的設置。 但是現在,如果我想重構Collaborator構造函數,我將打破ThingToTest。 再次,我仍然堅持希望有人可以提出一種方法來實際對該課程進行單元測試!

不確定這是否是我的最終答案,但我最終使用了proxyquire,因為這是到目前為止找到的最好的解決方案。 為了展示其工作原理,我將被測類分為各自的目錄,並將測試文件放在子“ test”目錄中。 這說明 proxyquire中的路徑是如何工作的(這花了我一些時間來弄清楚)。 所以,這就是我最終得到的結果:

/Collaborator.js

"use strict"

class Collaborator {
  constructor(settings) {
    console.log("Don't want this to be called!")
    this.settings = settings;
  }
}

module.exports = Collaborator

/ThingToTest.js

"use strict"

const Collaborator = require("./Collaborator")

class ThingToTest {
  constructor(settings) {
    this.helper = new Collaborator(settings)
  }
}

module.exports = ThingToTest

/test/ExampleTest.js

"use strict";

const proxyquire = require('proxyquire')
const mockCollaborator = sinon.stub();
const ThingToTest = proxyquire("../ThingToTest", { "./Collaborator" : mockCollaborator })

const assert = require("assert");
const sinon = require("sinon");

describe("ThingToTest", () => {
  let settings = "all the things"

  context("checking Collaborator in a more integration style test", () => {

    describe("constructor", () => {
      it("creates a Collaborator with provided settings", () => {
        let thing = new ThingToTest(settings);
        assert.equal(mockCollab.firstCall.calledWith(settings))
      })
    })
  })
})

注意proxyquire("../ThingToTest", { "./Collaborator" : mockCollaborator })內部的路徑如何匹配“ ThingToTest”使用的內容, 而不是測試類的路徑。 希望對其他人有所幫助,但我仍然歡迎其他想法和建議!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM