【问题标题】:How do I mock or fake behavior of a website to allow unit testing for certain JS functions如何模拟或伪造网站的行为以允许对某些 JS 功能进行单元测试
【发布时间】:2018-06-30 04:24:00
【问题描述】:

情况: 我刚开始学习对我的 JavaScript 代码进行单元测试,我想知道是否有办法伪造应用程序的行为以测试某些情况。我阅读了有关 sinon.js spy/stub/mock 的信息。然而,像往常一样 JS 有很多进一步的脚本和组合(即使用 mocha、chai、karma-jasmine),我希望有人能告诉我一个最佳实践。

举个例子: 如果我想在测试运行器中测试一个函数,它会根据窗口大小改变背景大小,那么触发不同的窗口大小(不是元素大小)以查看背景大小调整在多个工作中是很复杂的方面。

我已经测试了一些东西,例如

var resizeW = sinon.stub($.prototype, 'width').returns(600);
var resizeH = sinon.stub($.prototype, 'height').returns(1600);

// no effect - always takes the original view.height/width
viewport.setAttribute("content", "height=" + viewheight + "px, width=" + viewwidth + "px, initial-scale=1.0"); 

// new window is not testable in the root testrunner window
window.open + window.resizeTo() / window.resizeBy() 

// shows no effect
window.innerHeight = '120'; window.innerWidth = '500';

// provides no possibility to assume different dimensions
$(window).trigger('resize');

// provides no possibility to assume different dimensions
$(document).trigger('resize');

// provides no possibility to assume different dimensions
window.dispatchEvent(new Event('resize'));

使用 iframe 会很乏味,即在原始 HTML 和测试运行 HTML 之间与 CSS 和 jQuery 发生冲突。

我希望有人可以提出一种方便的方法来实现这一点。

【问题讨论】:

  • 这是一个使用窗口调整大小的坏例子,因为 CSS 媒体查询会为您处理所有这些计算。 IOE 不需要任何 JavaScript。
  • 并非如此。让我们假设智能手机上的键盘在 textarea 点击时弹出并将整个内容缩小到剩余的窗口大小 - 这里你需要调整内容,这更容易用 js 处理。当您需要不断调整内容而不是逐步调整时,它也很出色......
  • 你试过了吗:Selenium web driver seleniumhq.org or Headless Chrome chromium.googlesource.com/chromium/src/+/lkgr/headless/…
  • @jeff 在大多数情况下都是正确的,我想说,部分原因是 CSS 在不同的线程中处理这个问题,而不是对 resize 事件的反应在同一线程中运行线程作为应用程序的其余部分,导致性能下降,通常很明显。

标签: javascript jquery unit-testing jasmine sinon


【解决方案1】:

单元测试旨在断言应用程序的逻辑和状态位按预期工作。

虽然您当然可以设置一个单元测试套件来在浏览器中针对您的应用程序表示层进行断言,但这可能不是可行的方法,因为您知道,很难模拟某些浏览器行为

正如@SteveB 在他的评论中所建议的那样,端到端测试工具可能比单元测试更适合您。此类工具允许在浏览器中运行您的实时应用程序并做出一些断言,同时直接控制浏览器行为,因此您不会在模拟 jQuery 的方法甚至使用它时遇到麻烦。

Nightwatchnightmare.jsSelenium 是执行端到端测试的常用工具。

另一个可能适合您的工具是Quixote,一个用于 css 断言的工具。

有时,在处理前端代码时,即使在对基本功能进行单元测试时,也必须模拟原生浏览器 api:在这种情况下,writing tight functions 是要走的路。

【讨论】:

    【解决方案2】:

    听起来你真正关心的是你的应用程序如何与浏览器集成,而不一定是你自己控制的逻辑。这似乎是一个集成测试,在这种情况下,您不希望删除浏览器功能。在这种情况下,其他人提到的一些测试框架,如 Selenium 可能是一个不错的选择(我可能还建议使用 Puppeteer,它具有 setViewport 函数)。

    如果您将依赖项外部化,也可以将其编写为单元测试,如果有内部逻辑值得单独测试,通过将宽度和高度传递到您的代码并验证您的代码响应适当,但听起来好像这里的逻辑主要是与浏览器/jQuery/DOM 集成。

    关于最佳实践,要记住和探索的一个重要格言是don't mock code that you don't own - 如果这样做,您就是在嘲笑您无法控制的行为,并且可能会在您的控制下发生变化,并且可能会允许您的实施泄漏到您的测试中。

    【讨论】:

      猜你喜欢
      • 2014-01-01
      • 2021-09-20
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 2017-07-17
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多