javascript - 类实例不能传递给包含 Jasmine describe- 和 it-blocks 的函数
问题描述
好的,我的设置有点复杂,但我得到的错误仍然很有趣。
我有一个用于 webdriverio 测试运行程序的 Jasmine 测试套件,其中包含一个在其他地方声明的函数,我将一个类的实例传递给该函数。该函数又包含更多嵌套的 describe- 和 it- 块。
const MyObject = require('./my-object');
const { passObject, myFunction } = require('./obj-fns');
var myObjectInstance;
describe("testing passing objects as parameters", function() {
beforeAll(function() {
myObjectInstance = new MyObject();
});
it("for a class instance inside describe/it block directly", function() {
browser.pause(250);
expect(myObjectInstance).not.toBe(undefined);
expect(myObjectInstance.selector).toBe("object-class-instance");
});
it("for a function inside describe/it block directly", function() {
browser.pause(250);
expect(myFunction).not.toBe(undefined);
expect(myFunction().selector).toBe("object-function");
});
passObject(myFunction, myObjectInstance);
});
my-object.js
class MyObject {
constructor() {
this.selector = "object-class-instance";
}
}
module.exports = MyObject;
obj-fns.js
module.exports.passObject = function(fn, obj) {
describe("inside a function that has a describe block", function() {
it("and an it block for a class instance", function() {
browser.pause(250);
expect(obj).not.toBe(undefined);
expect(obj.selector).toBe("object-class-instance");
});
it("and an it block for a function", function() {
browser.pause(250);
expect(fn).not.toBe(undefined);
expect(fn().selector).toBe("object-function");
})
});
}
module.exports.myFunction = function() {
return {
selector: "object-function"
}
}
除了检查对象(通过的类实例)是否未定义的函数it
内的块之外,所有测试都通过。passObject
pass: testing passing objects as parameters for a class instance inside describe/it block directly
pass: testing passing objects as parameters for a function inside describe/it block directly
pass: testing passing objects as parameters inside a function that has a describe block and an it block for a function
fail: testing passing objects as parameters inside a function that has a describe block and an it block for a class instance (chrome_undefinedVersion with 0-0 runner)
Error: Expected undefined not to be undefined.
at <Jasmine>
at UserContext.<anonymous> (C:\dev\eclipse-workspace\FrontendTesting\Daimler.Van.SPP.Dashboard.Web.FrontendTesting\spec\obj-fns.js:6:29)
at <Jasmine>
这是否符合设计,如果是,我如何将类实例传递给具有 describe- 和 it-blocks 的函数?还是我错过了什么?
解决方案
问题是当你调用它时,它会在变量被赋值之前立即passObject(myFunction, myObjectInstance);
执行。因此,当内部代码运行时,它会为每个测试使用as ,因为那是当时传入的内容。myObjectInstance
passObject
obj
undefined
您可以改为做一些不同的事情并将工厂函数传递给您的测试函数。这将允许您在主要测试和其中的测试之间共享代码,passObject
同时仍然允许您灵活地passObject
使用不同的对象运行。
下面是代码的样子:
module.exports.passObject = function(fn, createObj) {
describe("inside a function that has a describe block", function() {
beforeAll(function() {
this.obj = createObj();
});
it("and an it block for a class instance", function() {
browser.pause(250);
expect(this.obj).not.toBe(undefined);
expect(this.obj.selector).toBe("object-class-instance");
});
it("and an it block for a function", function() {
browser.pause(250);
expect(fn).not.toBe(undefined);
expect(fn().selector).toBe("object-function");
})
});
}
passObject
现在采用创建obj
而不是仅采用obj
. 它还使用this
上下文将该对象传递给测试。
使用它时,您需要提取对象的初始化并在两个地方重用它:
function createInstance { return new MyObject(); }
describe("testing passing objects as parameters", function() {
beforeAll(function() {
myObjectInstance = createInstance()
});
it("for a class instance inside describe/it block directly", function() {
browser.pause(250);
expect(myObjectInstance).not.toBe(undefined);
expect(myObjectInstance.selector).toBe("object-class-instance");
});
it("for a function inside describe/it block directly", function() {
browser.pause(250);
expect(myFunction).not.toBe(undefined);
expect(myFunction().selector).toBe("object-function");
});
passObject(myFunction, createInstance);
});
这会导致轻微的代码重复,因为在这两种情况下都会beforeAll
调用一个函数,将结果分配给一个变量并在测试中重新使用该变量。这很好,因为变量在两种情况下都不同,因此不同的测试不必将其称为相同的东西。但是,如果您想冒稍微混淆代码的风险,您甚至可以消除这种重复。
首先,将整个beforeAll
代码提取到一个
function setup() {
this.instance = new MyObject();
}
然后你可以beforeAll
直接在你的
// in the main tests
beforeAll(setup)
module.exports.passObject = function(fn, setupFn) {
describe("inside a function that has a describe block", function() {
beforeAll(setupFn);
/* ...tests...*/
}
}
但是,这意味着两个测试必须引用相同的东西:this.instance
并且目前还不清楚应该或将在this
测试的上下文中初始化什么。此外,一组测试可能需要初始化更多的东西,而另一组则更少,例如,一个可能只使用this.instance
另一个可能还需要this.foo
。
因此,如果您选择这条路线,则必须检查测试范围,以免设置功能不断增长以适应每个可能的属性。
此外,如果您想为同一事物使用不同的名称,那么您仍然可以只拥有两个指向相同值的属性。这将减轻两组测试的一些强加样式。例如:
function setup() {
//for the main tests
this.myObjectInstance = new MyObject();
//for `passObject` just alias the same thing:
this.obj = this.myObjectInstance;
}
推荐阅读
- javascript - 使用 next 方法创建一个迭代器,该方法在调用 .next 时返回数组的每个值
- java - ETL 设计:我应该使用什么队列而不是我的 SQL 表并且仍然能够并行处理?
- sql-server - SQL 中连接、实例和会话之间的区别
- c++ - std::accumulate 可以抛出吗?
- excel - 如何在 VBA 中找到控件的父用户窗体
- javascript - Await 仅在异步函数中有效
- excel - 如何验证电子邮件地址格式?
- google-cloud-platform - 在 GCP 中查询项目列表
- string - 恐慌:运行时错误:切片超出范围 [2:1]
- c# - C#:运行程序并用 if 语句回答输入后,我如何让程序继续提问?