【问题标题】:Angular Accept.js breaking unit tests 'Reference Error: Accept is not defined'Angular Accept.js 破坏单元测试“参考错误:未定义接受”
【发布时间】:2018-06-05 10:47:13
【问题描述】:

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

some.component.ts

ngOnInit {
  this.addAcceptJsScript();
}

private addAcceptJsScript(): void {
  const element = document.createElement('script');
  element.src = environment.acceptJsUrl;
  element.type = 'text/javascript';
  document.getElementsByTagName('head')[0].appendChild(element);
}

some.service.ts

declare var Accept: any;

@Injectable()
export class SomeService {
  private sendPaymentToAuthNet(paymentPayload): void {
    Accept.dispatchData(paymentPayload, this.handleAuthNetResponse);
  }
}

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

但是我在使用 API 的服务中的单元测试没有任何参考 Accept 是什么所以当它尝试测试我调用 Accept.dispatchData(...) 的代码行时,测试错误说 '参考错误:未定义接受".

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

【问题讨论】:

    标签: angular jasmine karma-jasmine authorize.net accept.js


    【解决方案1】:

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

    document 最好是提供者,因为它应该在某些时候被模拟以避免将脚本元素添加到真实的 DOM。已经有DOCUMENT 提供程序可以注入到组件中,而不是document 全局。并在测试台上被嘲笑:

    {
      provide: DOCUMENT,
      useValue: jasmine.createSpyObj('document', ['createElement', 'getElementsByTagName'])
    }
    

    createElementgetElementsByTagName Jasmine 间谍应配置为返回正确的模拟对象。

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

    【讨论】:

      【解决方案2】:

      我只需要在我的 karma.config 文件对象中包含 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 应该提供的帮助。另一种方法是在 beforeEach 中定义 window.Accept,这对 Angular 来说不那么惯用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-25
      • 2019-04-18
      • 2014-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多