这很简单:该原型不包含名为text 的函数,因此会出现错误。我写了这个快速脚本来验证:
import { jsPDF } from "jspdf";
console.dir(jsPDF);
console.log("prototype", jsPDF.prototype);
console.log("prototype has text?", typeof jsPDF.prototype.text !== "undefined");
const pdf = new jsPDF();
console.log(pdf.text);
哪个输出这个
$ node test.js
[Function: I] {
API: {
events: [
[Array], [Array],
....
....
RadioButton: [Function: ft],
CheckBox: [Function: pt],
TextField: [Function: gt],
PasswordField: [Function: mt],
Appearance: {
CheckBox: [Object],
RadioButton: [Object],
createDefaultAppearanceStream: [Function: createDefaultAppearanceStream],
internal: [Object]
}
},
getPageSize: [Function (anonymous)],
__bidiEngine__: [Function (anonymous)]
}
prototype { __bidiEngine__: [Function (anonymous)] }
prototype has text? false
[Function (anonymous)]
看了一下the source,jsPdf的原型基本上没有添加任何东西。当您通过调用构造函数创建新对象时,所有插件和 API 方法都会添加/绑定到 实例。
监视text 方法
您无需尝试在原型上查找方法,而只需监视实例方法。
const pdf = new jsPDF();
const spy = sinon.spy(pdf, "text");
const transcriptString = "test transcript string";
pdf.text(transcriptString, 10, 10);
console.log("called?", spy.called); // ==> true
在您使用自己的 createPDF() 函数的示例中,这将不起作用,因为您在闭包中屏蔽了实例的访问。您需要某种方式连接到实例创建过程。有几种方法可以“解决”这个问题。一种方法是提取一个工厂函数来创建jsPDF 实例和一个相关的setter,让您替换被调用的构造函数。另一种方法是在测试中使用"link seam" 来替换jspdf 模块。
使用链接接缝(模块更换)
看起来像这样:
import {jsPDF} from 'jspdf';
// later ... in your test
let createdInstance;
let spy;
const createPdf = proxyquire("../src/createPdf", {
jspdf: {
jsPDF: (...args) => {
createdInstance = new jsPDF(...args);
sinon.spy(createdInstance, 'text');
return createdInstance;
});
}
});
pdf.createPDF(transcriptString)
expect(spy).to.have.been.called
这具有不需要修改或重构原始代码的优点,但它是非常特定于环境的。 proxyquire 只能在 Node 中工作,你需要为 Webpack 提供其他东西,为 Vite、Jest 等提供不同的解决方案。
“手动”DI
如果你稍微重构一下代码,无论你使用什么环境或框架,它都会更容易测试:
export class PdfCreator(){
constructor(opts) {
this.jsPDF = opts?.stubs?.jsPDF || jsPDF;
}
createPdf(text){
const transcriptPdfDoc = new this.jsPDF()
transcriptPdfDoc.text(transcriptString, 10, 10)
transcriptPdfDoc.save('test.pdf')
}
}
const defaultInstance = new PdfCreator();
export default createPdf = (text) => defaultInstance.createPdf();
通过这种方法,您可以完全控制创建过程。如果你想测试pdf创建,你可以创建一个creator = new PdfCreator({stubs: {jsPDF:spy}});并调用creator.createPdf('foo')来测试它。