- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在 Node 项目中创建一个基本类,并且我想使用 Jest 来测试它。我收到一个错误,暗示在测试中使用“严格”模式,我想避免/修复该错误
<小时/>~/lib/LogRecord.jsmodule.exports = class LogRecord {
constructor(level, message, timestamp) {
this.level = level;
this.message = message;
this.timestamp = timestamp ? timestamp : Date.now();
}
get level() {
return this.level;
}
get message() {
return this.message;
}
get timestamp() {
return this.timestamp;
}
}
我正在用这个测试它:
let LogRecord = require('../lib/logRecord');
describe('Test LogRecord functionality', () => {
test('LogRecord constructor', () => {
let timestamp = Date.now();
let logRecord = new LogRecord('INFO', 'Test Message', timestamp);
expect(logRecord.level).toBe('INFO');
expect(logRecord.message).toBe('Test Message');
expect(logRecord.timestamp).toBe(timestamp);
});
test('LogRecord is read-only', () => {
let timestamp = Date.now();
let logRecord = new LogRecord('INFO', 'Test Message', timestamp);
logRecord.level = 'WARN'
logRecord.message = 'New Message'
logRecord.timestamp = Date.now();
expect(logRecord.level).toBe('INFO');
expect(logRecord.message).toBe('Test Message');
expect(logRecord.timestamp).toBe(timestamp);
});
});
当我运行 npm test
时,我在两个 LogRecord 测试中都收到以下错误:
Test LogRecord functionality › LogRecord constructor
TypeError: Cannot set property level of #<LogRecord> which has only a getter
1 | module.exports = class LogRecord {
2 | constructor(level, message, timestamp) {
> 3 | this.level = level;
| ^
4 | this.message = message;
5 | this.timestamp = timestamp ? timestamp : Date.now();
6 | }
at new LogRecord (lib/logRecord.js:3:9)
at Object.test (test/logRecord.test.js:6:25)
const data = new WeakMap();
let levelKey = {id:'level'};
let messageKey = {id:'message'};
let timestampKey = {id:'timestamp'};
module.exports = class LogRecord {
constructor(level, message, timestamp) {
data.set(levelKey, level);
data.set(messageKey, message);
data.set(timestampKey, timestamp ? timestamp : Date.now());
}
get level () {
return data.get(levelKey)
}
get message () {
return data.get(messageKey)
}
get timestamp () {
return data.get(timestampKey)
}
}
最佳答案
测试的目的是确保您的代码按照您的想法运行。考虑下面的类:
class Foo {
constructor (bar) {
this._bar = bar;
}
get bar () {
return this._bar;
}
}
此处 bar
是只读,无法设置 bar
属性:
let foo = new Foo('a foo');
foo.bar; // 'a foo'
foo.bar = 'am not'; // TypeError!
模块问题并不真正相关:因为注释中链接的 Logar 类主体总是严格模式,无论如何。
因此,如果您希望某个属性是只读的,则无需担心写入它。工作流程可能如下所示:
class Foo {}
并构造一个实例 foo = new Foo()
如果您不需要只读属性,您可以添加一个 setter :
class Foo {
constructor (bar) {
this._bar = bar;
}
get bar () {
return this._bar;
}
set bar (value) {
this._bar = value;
}
}
在这种情况下,您需要添加一个测试来设置 bar
并读取更改后的值。
* 你可能想知道为什么这个测试在这里,当这种行为由规范保证时,我认为测试是必要的,因为有人可以(对调用者透明地)将类重构为老式构造函数并创建错误向量:
// post refactor Foo
const Foo = function Foo(bar) {
this.bar = bar; // danger! now writable!
};
希望此类事情能够被知识渊博的审阅者发现,但无论如何我都会编写测试。
如果您想要的是在构造函数中设置的保证只读属性,这里有一个方法:
const data = new WeakMap();
module.exports = class Foo () {
constructor (bar) {
data.set(this, bar);
}
get bar () {
return data.get(this);
}
};
因为 data
未导出,所以外部代码无法更改它。尝试设置实例的 bar
属性将会抛出异常。这比仅使用 getter 和 setter 定义下划线属性要复杂一些,但如果这是您想要的,那么...我知道这种模式,因为我已经使用过它。
您只能为每个模块创建一个weakmap,而不是为每个类或实例创建一个weakmap。弱映射存储一个唯一的数据条目,该数据条目是针对各个实例的(即this
):
const data = new WeakMap();
module.exports = {
Foo: class Foo () {
constructor (bar) {
data.set(this, bar);
}
get bar () {
return data.get(this);
}
},
Bar: class Bar () {
constructor (prop1, prop2) {
// for multiple props we'll store an object...
data.set(this, { prop2, prop1 });
}
get prop1 () {
// ...and retrieve it and access it's props to return
return data.get(this).prop1;
}
get prop2 () {
return data.get(this).prop2;
}
}
};
请注意,使用 getter 设置 props 但没有 setter 仍然会抛出...
// in someotherfile.js
const { Foo } = require('path/to/file/with/foo.js');
const foo = new Foo('imma foo');
foo.bar; // 'imma foo'
foo.bar = 'no not really'; // TypeError!
// you can still set random properties that don't have a getter:
foo.baz = 'I do not throw';
foo.baz; // 'I do not throw'
关于javascript - 为 Node CommonJS 模块创建不可变类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51613186/
为什么禁用类型像 type t = A of int | B of string * mutable int 虽然允许此类类型: type t = A of int | B of string * i
我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有某种类型提示而不是不可变的。 所以我有这样的东西: class ConnectionConfig(NamedTuple): nam
我需要转到引用的结构: class SearchKnot { var isWord : Bool = false var text : String = "" var to
如sec 10.4.3中所述 当控制进入执行时,执行以下步骤 功能对象F(调用者)中包含的功能代码的上下文 提供thisArg,而调用方提供argumentsList: 如
i make a game that start display Activity indicator And activity indicator bottom display UiLable wi
编辑:我在这里不断获得支持。只是为了记录,我认为这不再重要。自从我发布它以来我就不再需要它了。 我想在 Scala 中执行以下操作... def save(srcPath: String, destP
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
如果您在Kotlin中访问List类型的Java值,则将获得(Mutable)List!类型。 例如。: Java代码: public class Example { public stati
我编写了 str 类(内置)的以下扩展,以便执行以下操作:假设我有字符串 "Ciao" ,通过做"Ciao" - "a"我想要的结果是字符串 "Cio" 。这是执行此操作的代码,并且运行良好: cla
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
我正在为我的公司设计一个数据库来管理商业贷款。每笔贷款都可以有担保人,可以是个人或公司,在借款业务失败时作为财务支持。 我有 3 个表:Loan、Person 和 Company,它们存储明显的信息。
我使用二进制序列化从 C# 类中保存 F# 记录。一切正常: F#: type GameState = { LevelStatus : LevelStatus
import javax.swing.JOptionPane; public class HW { public static void main(String[] args) { Strin
使用 flatbuffer mutable 有多少性能损失? 是否“正确”使用 FlatBuffers 来拥有一个应该可编辑的对象/结构(即游戏状态) 在我的示例中,我现在有以下类: class Ga
std::function create_function (args...) { int x = initial_value (args...); return [x] () mut
我需要在 for 循环中找到用户输入的字符。我通常会这样做 如果(句子[i] == 'e') 但是因为在这里,'e' 将是一个单字母字符变量,我不知道如何获取要比较的值。我不能只输入 if (sent
我有一个这样的算法: let seed: Foo = ... let mut stack: Vec = Vec::new(); stack.push(&seed); while let Some(ne
这个问题可能看起来非常基础,但我很难弄清楚如何做。我有一个整数,我需要使用 for 循环来循环整数次。 首先,我尝试了—— fn main() { let number = 10; // An
如果我有以下结构: struct MyStruct { tuple: (i32, i32) }; 以及以下函数: // This will not compile fn function(&mut s
我希望在每个 session 的基础上指定列的默认值。下面的脚本不起作用,但描述了我想如何使用它。我目前使用的是 MySQL 5.5.28,但如果需要可以升级。 CREATE TABLE my_tbl
我是一名优秀的程序员,十分优秀!