Angular Accept.js破坏单元测试的“引用错误:未定义Accept”

Angular Accept.js破坏单元测试的“引用错误:未定义Accept”,angular,jasmine,karma-jasmine,authorize.net,accept.js,Angular,Jasmine,Karma Jasmine,Authorize.net,Accept.js,我有一个angular组件,它使用Authorize.nets Accept.js SDK来完成付款。我不想加载Accept.js脚本,除非用户在付款屏幕上,所以我通过在组件中调用onInit的方法将脚本添加到页面中 一些 一些服务 这对于用户来说很好,因为脚本加载到DOM中,并且在组件调用使用Accept API的服务时可用 但是,我在使用API的服务中进行的单元测试在尝试测试我调用Accept.dispatchData的代码行时,没有任何引用Accept是什么。。。测试错误显示为“引用错误:

我有一个angular组件,它使用Authorize.nets Accept.js SDK来完成付款。我不想加载Accept.js脚本,除非用户在付款屏幕上,所以我通过在组件中调用onInit的方法将脚本添加到页面中

一些

一些服务

这对于用户来说很好,因为脚本加载到DOM中,并且在组件调用使用Accept API的服务时可用

但是,我在使用API的服务中进行的单元测试在尝试测试我调用Accept.dispatchData的代码行时,没有任何引用Accept是什么。。。测试错误显示为“引用错误:未定义接受”


我尝试过各种模仿Accept的方法,但没有一种可以用于测试。如何将mock Accept注入到服务中,以便在代码尝试使用它时声明它?

测试问题通常表明应用程序设计中存在缺陷

文档最好应该是一个提供者,因为它应该在某个时候被模拟,以避免向真实的DOM中添加脚本元素。已经有一个提供程序可以注入组件而不是全局文档。并在试验台上进行模拟:

{
  provide: DOCUMENT,
  useValue: jasmine.createSpyObj('document', ['createElement', 'getElementsByTagName'])
}
其中createElement和getElementsByTagName Jasmine spies应该配置为返回正确的模拟对象


出于可测试性的原因,Accept也应该成为提供者。该值可以分配给窗口['Accept'],如中所示,并在测试台上模拟。

我只需要在karma.config的my files对象中包含Accept.js CDN的路径

files: [
  { pattern: './src/test.ts', watched: false },
  { pattern: './node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: true },
  { pattern: 'https://jstest.authorize.net/v1/Accept.js', nonull: true }
]

我希望您运行的是单元测试,而不是集成。在单元测试中,针对真实事物的测试是不好的,因为这会打破隔离。我不是针对它进行测试,我只是需要定义它。这里的要点是,真实的Accept.dispatchData,更重要的是,document.createElement甚至不应该有机会在单元测试中被调用,因为它可能会产生副作用。这就是DI应该帮助的。另一种方法是在beforeach中定义window.Accept,这对Angular来说不太习惯。
{
  provide: DOCUMENT,
  useValue: jasmine.createSpyObj('document', ['createElement', 'getElementsByTagName'])
}
files: [
  { pattern: './src/test.ts', watched: false },
  { pattern: './node_modules/@angular/material/prebuilt-themes/indigo-pink.css', included: true, watched: true },
  { pattern: 'https://jstest.authorize.net/v1/Accept.js', nonull: true }
]