bun 单元测试

bun test

Bun 附带了一个快速、内置、兼容 Jest 的测试运行程序。测试使用 Bun 运行时执行,并支持以下功能。

  • TypeScript 和 JSX
  • 生命周期 hooks
  • 快照测试
  • UI 和 DOM 测试
  • 使用 --watch 的监视模式
  • 使用 --preload 预加载脚本

Bun 旨在与 Jest 兼容,但并非所有内容都已实现。若要跟踪兼容性,请参阅此跟踪问题。

运行测试

bun test

测试是用 JavaScript 或 TypeScript 编写的,带有类似 Jest 的 API。有关完整文档,请参阅编写测试。

// main.test.ts

import { expect, test } from "bun:test";

test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});

运行器以递归方式在工作目录中搜索与以下模式匹配的文件:

  • *.test.{js|jsx|ts|tsx}
  • *_test.{js|jsx|ts|tsx}
  • *.spec.{js|jsx|ts|tsx}
  • *_spec.{js|jsx|ts|tsx}

您可以通过将其他位置参数传递给 bun test 来过滤要运行的测试文件集。路径与其中一个筛选器匹配的任何测试文件都将运行。通常,这些过滤器将是文件或目录名称;尚不支持 glob 模式。

bun test <filter> <filter> ...

要按测试名称进行筛选,请使用 -t/--test-name-pattern 标志。

# run all tests or test suites with "addition" in the name
bun test --test-name-pattern addition

若要在测试运行程序中运行特定文件,请确保路径以 .// 或 / 开头,以将其与筛选器名称区分开来。

bun test ./test/specific-file.test.ts

测试运行程序在单个进程中运行所有测试。它加载所有 --preload 脚本(有关详细信息,请参阅生命周期),然后运行所有测试。如果测试失败,测试运行程序将退出,并显示非零退出代码。

使用 --timeout 标志指定每个测试的超时(以毫秒为单位)。如果测试超时,它将被标记为失败。默认值为 5000

# default value is 5000
bun test --timeout 20

使用 --rerun-each 标志可多次运行每个测试。这对于检测片状或非确定性测试失败非常有用。

bun test --rerun-each 100

使用 --bail 标志在预定的测试失败次数后提前中止测试运行。默认情况下,Bun 将运行所有测试并报告所有故障,但有时在 CI 环境中,最好提前终止以减少 CPU 使用率。

# bail after 1 failure
bun test --bail

# bail after 10 failure
bun test --bail 10

与 bun run 类似,您可以将 --watch 标志传递给 bun test,以监视更改并重新运行测试。

bun test --watch

生命周期 hooks

Bun 支持以下生命周期钩子:

Hook描述
beforeAll在所有测试之前运行一次。
beforeEach在每次测试之前运行。
afterEach在每次测试后运行。
afterAll在所有测试后运行一次。

这些钩子可以在测试文件中定义,也可以在预加载了 --preload 标志的单独文件中定义。

 bun test --preload ./setup.ts

有关完整文档,请参阅测试>生命周期。

Mocks

使用 bun.mock 创建 mock 函数。模拟在测试之间自动重置。

import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());

test("random", () => {
  const val = random();
  expect(val).toBeGreaterThan(0);
  expect(random).toHaveBeenCalled();
  expect(random).toHaveBeenCalledTimes(1);
});

或者,您可以使用 jest.fn(),它的行为是完全相同的。

import { test, expect, jest } from "bun:test";

const random = jest.fn(() => Math.random());

有关完整文档,请参阅测试>模拟。

快照测试

bun test 支持快照测试。

// example usage of toMatchSnapshot
import { test, expect } from "bun:test";

test("snapshot", () => {
  expect({ a: 1 }).toMatchSnapshot();
});

要更新快照,请使用 --update-snapshots 标志。

bun test --update-snapshots

有关完整文档,请参阅测试>快照。

UI 和 DOM 测试

Bun 与流行的 UI 测试库兼容:

  • HappyDOM快乐DOM
  • DOM Testing LibraryDOM 测试库
  • React Testing LibraryReact 测试库

有关完整文档,请参阅测试> DOM 测试。

性能

Bun 的测试运行速度很快。

编写测试

从内置的 bun:test 模块中导入类似 Jest 的 API 来定义测试。从长远来看,Bun 旨在实现与 Jest 的完全兼容;目前,仅支持一组有限的 expect 匹配器。

基本用法

定义一个简单的测试:

// math.test.ts

import { expect, test } from "bun:test";

test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});

就像在 Jest 中一样,你可以在不导入它们的情况下使用 describe、test、expect 和其他函数。但与 Jest 不同,它们没有被注入到全局作用域中。相反,Bun 转译器会自动在内部注入一个来自 bun:test 的导入。

typeof globalThis.describe; // "undefined"
typeof describe; // "function"

这种转译器的集成仅在bun测试期间发生,并且只针对测试文件和预加载脚本。实际上,对于最终用户来说,这没有什么明显区别。

可以使用 describe 将测试分组为套件。

// main.test.ts

import { expect, test, describe } from "bun:test";

describe("arithmetic", () => {
  test("2 + 2", () => {
    expect(2 + 2).toBe(4);
  });

  test("2 * 2", () => {
    expect(2 * 2).toBe(4);
  });
});

测试也可以是异步的。

import { expect, test } from "bun:test";

test("2 * 2", async () => {
  const result = await Promise.resolve(2 * 2);
  expect(result).toEqual(4);
});

或者,使用 done 回调来标记完成。如果你在测试定义中将 done 回调作为一个参数包含进来,你必须调用它,否则测试将挂起。

import { expect, test } from "bun:test";

test("2 * 2", done => {
  Promise.resolve(2 * 2).then(result => {
    expect(result).toEqual(4);
    done();
  });
});

可以通过给可选的第三个参数传递一个数字来指定每个测试的超时时间(以毫秒为单位)。

import { test } from "bun:test";

test("wat", async () => {
  const data = await slowOperation();
  expect(data).toBe(42);
}, 500); // test must run in <500ms

test.skip

用 test.skip 跳过个别测试。这些测试将不会被运行。

import { expect, test } from "bun:test";

test.skip("wat", () => {
  // TODO: fix this
  expect(0.1 + 0.2).toEqual(0.3);
});

test.todo

使用 test.todo 将测试标记为待办事项。这些测试将会运行,并且测试运行器会期望它们失败。如果它们通过了,那么将会提示你将它们标记为常规测试。

import { expect, test } from "bun:test";

test.todo("fix this", () => {
  myTestFunction();
});

要仅运行标记为 todo 的测试,请使用 bun test --todo。

bun test --todo

test.only

要运行特定的测试或测试套件,请使用 test.only() 或 describe.only()。一旦声明,运行 bun test --only 将只执行被标记为 .only() 的测试/测试套件。如果在声明了 test.only() 的情况下运行 bun test 但没有使用 --only 选项,那么将执行给定套件中所有测试,直到遇到带有 .only() 的测试。在两种执行场景中,describe.only() 的功能都相同。

import { test, describe } from "bun:test";

test("test #1", () => {
  // does not run
});

test.only("test #2", () => {
  // runs
});

describe.only("only", () => {
  test("test #3", () => {
    // runs
  });
});

以下命令只会执行测试 #2 和 #3。

bun test --only

以下命令会执行测试#1、#2和#3。

bun test

test.if

要条件性地运行测试,请使用 test.if()。如果条件为真值,则会运行测试。这对于仅在特定架构或操作系统上运行的测试特别有用。

test.if(Math.random() > 0.5)("runs half the time", () => {
  // ...
});

const macOS = process.arch === "darwin";
test.if(macOS)("runs on macOS", () => {
  // runs if macOS
});

为了基于某些条件跳过测试,可以使用 test.skipIf() 或 describe.skipIf()。

const macOS = process.arch === "darwin";

test.skipIf(macOS)("runs on non-macOS", () => {
  // runs if *not* macOS
});

test.each

要在测试表中为多个 case 返回一个函数,请使用test.each。

const cases = [[1, 2, 3], [3, 4, 5]];

test.each(cases)("%p + %p should be %p", (a, b, expected) => {
    // runs once for each test case provided
})

根据标签的类型,可以对其格式进行多种设置。

%ppretty-format
%sString
%dNumber
%iInteger
%fFloating point
%jJSON
%oObject
%#Index of the test case
%%Single percent sign (%)

 匹配器

Bun 实现了以下匹配器。全面兼容 Jest 的路线图正在制定中;在这里跟踪进度。

.not
.toBe()
.toEqual()
.toBeNull()
.toBeUndefined()
.toBeNaN()
.toBeDefined()
.toBeFalsy()
.toBeTruthy()
.toContain()
.toStrictEqual()
.toThrow()
.toHaveLength()
.toHaveProperty()
.extend
.anything()
.any()
.arrayContaining()
.assertions()
.closeTo()
.hasAssertions()
.objectContaining()
.stringContaining()
.stringMatching()
.addSnapshotSerializer()
.resolves()
.rejects()
.toHaveBeenCalled()
.toHaveBeenCalledTimes()
.toHaveBeenCalledWith()
.toHaveBeenLastCalledWith()
.toHaveBeenNthCalledWith()
.toHaveReturned()
.toHaveReturnedTimes()
.toHaveReturnedWith()
.toHaveLastReturnedWith()
.toHaveNthReturnedWith()
.toBeCloseTo()
.toBeGreaterThan()
.toBeGreaterThanOrEqual()
.toBeLessThan()
.toBeLessThanOrEqual()
.toBeInstanceOf()
.toContainEqual()
.toMatch()
.toMatchObject()
.toMatchSnapshot()
.toMatchInlineSnapshot()
.toThrowErrorMatchingSnapshot()
.toThrowErrorMatchingInlineSnapshot()

生命周期钩子

测试运行器支持以下生命周期钩子。这对于加载测试装置、模拟数据和配置测试环境非常有用。

使用 beforeEach 和 afterEach 来执行每个测试的设置和拆卸逻辑。

import { beforeEach, afterEach } from "bun:test";

beforeEach(() => {
  console.log("running test.");
});

afterEach(() => {
  console.log("done with test.");
});

 使用 beforeAll 和 afterAll 执行每个范围的设置和拆卸逻辑。范围由定义钩子的位置决定。

将钩子范围限定为特定的 describe 块:

import { describe, beforeAll } from "bun:test";

describe("test group", () => {
  beforeAll(() => {
    // setup
  });

  // tests...
});

将钩子范围限定在测试文件:

import { describe, beforeAll } from "bun:test";

beforeAll(() => {
  // setup
});

describe("test group", () => {
  // tests...
});

为了将整个多文件测试运行范围限定在挂钩内,请在单独的文件中定义这些挂钩。

// setup.ts

import { beforeAll, afterAll } from "bun:test";

beforeAll(() => {
  // global setup
});

afterAll(() => {
  // global teardown
});

然后使用 --preload 在任何测试文件之前运行设置脚本。

$ bun test --preload ./setup.ts

为了避免每次运行测试时都需要输入 “--preload”,您可以将其添加到 bunfig.toml 文件中:

[test]
preload = ["./setup.ts"]

Mocks

使用模拟函数创建模拟数据。

import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());

test("random", async () => {
  const val = random();
  expect(val).toBeGreaterThan(0);
  expect(random).toHaveBeenCalled();
  expect(random).toHaveBeenCalledTimes(1);
});

另外,你也可以像Jest中那样使用 jest.fn() 函数,它的行为方式是完全一样的。

import { test, expect, jest } from "bun:test";
const random = jest.fn(() => Math.random());

test("random", async () => {
  const val = random();
  expect(val).toBeGreaterThan(0);
  expect(random).toHaveBeenCalled();
  expect(random).toHaveBeenCalledTimes(1);
});

mock() 的结果是一个被添加了一些额外属性的新函数。 

import { mock } from "bun:test";
const random = mock((multiplier: number) => multiplier * Math.random());

random(2);
random(10);

random.mock.calls;
// [[ 2 ], [ 10 ]]

random.mock.results;
//  [
//    { type: "return", value: 0.6533907460954099 },
//    { type: "return", value: 0.6452713933037312 }
//  ]

以下属性和方法在模拟函数上实现。

mockFn.getMockName()

mockFn.mock.calls

mockFn.mock.results

mockFn.mock.instances

mockFn.mock.contexts

mockFn.mock.lastCall

mockFn.mockClear()

mockFn.mockReset()

mockFn.mockRestore()

mockFn.mockImplementation(fn)

mockFn.mockImplementationOnce(fn)

mockFn.mockName(name)

mockFn.mockReturnThis()

mockFn.mockReturnValue(value)

mockFn.mockReturnValueOnce(value)

mockFn.mockResolvedValue(value)

mockFn.mockResolvedValueOnce(value)

mockFn.mockRejectedValue(value)

mockFn.mockRejectedValueOnce(value)

mockFn.withImplementation(fn, callback)

.spyOn()

可以使用SpyOn()创建一个Spy来跟踪对函数的调用,而无需将其替换为模拟函数。这些Spy可以传递给.toHaveBeenCalled()和.toHaveBeenCalledTimes()。

import { test, expect, spyOn } from "bun:test";

const ringo = {
  name: "Ringo",
  sayHi() {
    console.log(`Hello I'm ${this.name}`);
  },
};

const spy = spyOn(ringo, "sayHi");

test("spyon", () => {
  expect(spy).toHaveBeenCalledTimes(0);
  ringo.sayHi();
  expect(spy).toHaveBeenCalledTimes(1);
});

 mock.module

模块模拟允许你覆盖一个模块的行为。使用 mock.module(path: string, callback: () => Object) 来模拟一个模块。

import { test, expect, mock } from "bun:test";

mock.module("./module", () => {
  return {
    foo: "bar",
  };
});

test("mock.module", async () => {
  const esm = await import("./module");
  expect(esm.foo).toBe("bar");

  const cjs = require("./module");
  expect(cjs.foo).toBe("bar");
});

像 Bun 的其余部分一样,模块 mocks 同时支持import和require。

覆盖已导入的模块

如果你需要覆盖一个已经被导入的模块,你不需要做什么特别的事情。只需要调用 mock.module(),模块就会被覆盖。

import { test, expect, mock } from "bun:test";

// The module we're going to mock is here:
import { foo } from "./module";

test("mock.module", async () => {
  const cjs = require("./module");
  expect(foo).toBe("bar");
  expect(cjs.foo).toBe("bar");

  // We update it here:
  mock.module("./module", () => {
    return {
      foo: "baz",
    };
  });

  // And the live bindings are updated.
  expect(foo).toBe("baz");

  // The module is also updated for CJS.
  expect(cjs.foo).toBe("baz");
});
提升和预加载

如果你需要在导入模块之前确保对其进行模拟,你应该使用 --preload 在运行测试之前加载你的模拟。

// my-preload.ts
import { mock } from "bun:test";

mock.module("./module", () => {
  return {
    foo: "bar",
  };
});
bun test --preload ./my-preload

你可以在 bunfig.toml 文件中添加 preload:

[test]
# Load these modules before running tests.
preload = ["./my-preload"]

如果我 mock 一个已经被导入的模块,会发生什么?

如果你 mock 一个已经被导入的模块,该模块将在模块缓存中被更新。这意味着任何导入该模块的模块都将获得被 mock 的版本,但原始模块仍然会被评估。这意味着原始模块的任何副作用仍然会发生。

如果你想防止原始模块被评估,你应该在测试运行前使用 --preload 来加载你的模拟模块。

__mocks__目录和自动模拟 

目前尚不支持自动模拟。如果这阻止了你切换到Bun,请提交一个issue。

实现细节

模块模拟对 ESM 和 CommonJS 模块有不同的实现。对于ES模块,我们在 JavaScriptCore 中添加了补丁,允许 Bun 在运行时覆盖导出值并递归更新实时绑定。

从 Bun v1.0.19 开始,Bun会自动解析 mock.module() 中的规范参数,就像你进行了导入一样。如果解析成功,那么解析后的规范字符串将用作模块缓存中的键。这意味着你可以使用相对路径、绝对路径甚至模块名称。如果规范未解析,则使用原始规范作为模块缓存中的键。

解析后,被模拟的模块将存储在ES模块注册表和 CommonJS require 缓存中。这意味着你可以对模拟模块交替使用import和require。

回调函数是惰性调用的,只有当模块被导入或要求时才会调用。这意味着你可以使用mock.module()来模拟尚不存在的模块,而且你还可以使用mock.module()来模拟其他模块导入的模块。

日期和时间

bun:test 允许你在测试中更改时间。

这可以与以下任一项一起使用:

  • Date.now
  • new Date()
  • new Intl.DateTimeFormat().format()

计时器目前暂不支持,但可能在 Bun 的未来版本中支持。

setSystemTime

要更改系统时间,请使用 setSystemTime:

import { setSystemTime, beforeAll, test, expect } from "bun:test";

beforeAll(() => {
  setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
});

test("it is 2020", () => {
  expect(new Date().getFullYear()).toBe(2020);
});

为了支持使用 Jest 的 useFakeTimers 和 useRealTimers 的进行测试,可以使用 useFakeTimers 和 useRealTimers:

test("just like in jest", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
  expect(new Date().getFullYear()).toBe(2020);
  jest.useRealTimers();
  expect(new Date().getFullYear()).toBeGreaterThan(2020);
});

test("unlike in jest", () => {
  const OriginalDate = Date;
  jest.useFakeTimers();
  if (typeof Bun === "undefined") {
    // In Jest, the Date constructor changes
    // That can cause all sorts of bugs because suddenly Date !== Date before the test.
    expect(Date).not.toBe(OriginalDate);
    expect(Date.now).not.toBe(OriginalDate.now);
  } else {
    // In bun:test, Date constructor does not change when you useFakeTimers
    expect(Date).toBe(OriginalDate);
    expect(Date.now).toBe(OriginalDate.now);
  }
});

计时器 - 请注意,我们尚未实现用于模拟计时器的内置支持,但这在规划之中。

重置系统时间

要重置系统时间,不向 setSystemTime 传递任何参数:

import { setSystemTime, expect, test } from "bun:test";

test("it was 2020, for a moment.", () => {
  // Set it to something!
  setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
  expect(new Date().getFullYear()).toBe(2020);

  // reset it!
  setSystemTime();

  expect(new Date().getFullYear()).toBeGreaterThan(2020);
});

设置时区

要更改时区,可以将 $TZ 环境变量传递给 bun test。

TZ=America/Los_Angeles bun test

或在运行时设置 process.env.TZ:

import { test, expect } from "bun:test";

test("Welcome to California!", () => {
  process.env.TZ = "America/Los_Angeles";
  expect(new Date().getTimezoneOffset()).toBe(420);
  expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe(
    "America/Los_Angeles",
  );
});

test("Welcome to New York!", () => {
  // Unlike in Jest, you can set the timezone multiple times at runtime and it will work.
  process.env.TZ = "America/New_York";
  expect(new Date().getTimezoneOffset()).toBe(240);
  expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe(
    "America/New_York",
  );
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/430851.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

北京Excel表格线下培训班

Excel培训目标 熟练掌握职场中Excel所需的公式函数计算&#xff0c;数据处理分析&#xff0c;各种商务图表制作、动态仪表盘的制作、熟练使用Excel进行数据分析&#xff0c;处理&#xff0c;从复杂的数据表中把数据进行提取汇总 Excel培训形式 线下面授5人以内小班&#xff…

分享Web.dev.cn中国开发者可以正常访问

谷歌开发者很高兴地宣布&#xff0c;web.dev 和 Chrome for Developers 现在都可以通过 .cn 域名访问&#xff0c;这将帮助中国的开发者更加容易获取我们的内容。 在 .cn 域名上&#xff0c;我们已向您提供所有镜像后的内容&#xff0c;并提供支持的语言版本。 Web.dev 中国开…

uipath调用js代码

1&#xff0c;调用js代码&#xff0c;不带参数&#xff0c;没有返回值 为了去掉按钮的disabled属性 function(){ document.getElementsByClassName(submitBtn)[0].removeAttribute(disabled); } 2&#xff0c;调用js代码&#xff0c;带参数&#xff0c;没有返回值 输入参数&a…

el-dialog封装组件

父页面 <template><div><el-button type"primary" click"visible true">展示弹窗</el-button><!-- 弹窗组件 --><PlayVideo v-if"visible" :visible.syncvisible /></div> </template><sc…

Python-Numpy-计算向量间的欧式距离

两个向量间的欧式距离公式&#xff1a; a np.array([[2, 2], [4, 5], [6, 7]]) b np.array([[1, 1]]) # 使用L2范数计算 dev1 np.linalg.norm(a - b, ord2, axis1) # 使用公式计算 dev2 np.sqrt(np.sum((a - b) ** 2, axis1)) print(dev1.reshape((-1, 1)), dev2.reshape((…

掌握WhatsApp手机号质量评分:增加信息可达性

WhatsApp手机号质量评分是用于衡量用户手机号与平台互动的健康度&#xff0c;确保用户通讯时的合规性和安全性。在实掌握WhatsApp手机号质量评分实际应用中&#xff0c;这个评分会影响用户的消息发送的可达性。高质量的评分意味着用户的账户被视为可信赖的&#xff0c;其发送的…

2024最新ChatGPT网站源码, AI绘画系统

一、前言说明 R5Ai创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GP…

平替电容笔推荐:2024五大高口碑电容笔机型别错过!

现在电容笔已成为许多人工作、学习和创作的重要配件之一&#xff0c;它可以很好的提高我们的书写、绘画效率&#xff0c;无纸化学习也能减轻我们书本重量&#xff0c;让学习更加高效&#xff0c;然而&#xff0c;市场上电容笔种类繁&#xff0c;也少不了一些质量不佳的产品&…

掼蛋“六必治”策略

“六必治”&#xff0c;即是指当对手手中只剩下六张牌的时候&#xff0c;我们不管是用炸弹还是登基牌还是其他大牌都要及时压制对手&#xff0c;夺得出牌权&#xff0c;不能让他再次出牌&#xff0c;防止他有一手整牌或者一炸加上一手牌。 对手剩六张牌&#xff0c;有以下几种情…

正大国际:期货结算价是如何理解呢?结算价有什么作用?

如何理解期货结算价&#xff1a; 什么是商品期货当日结算价&#xff0c; 商品期货当日结算价是指某一期货合约当日交易期间成交价格按成交量的加权平均价。当日 无成交的&#xff0c;当日结算价按照交易所相关规定确定。 股指期货当日结算价是指某一期货合约当日交易期间最后一…

The Design and Implementation of a Capacity-Variant Storage System——论文泛读

FAST 2024 Paper 分布式元数据论文整理 问题 随着SSD的使用&#xff0c;其性能稳步下降。如图1所示&#xff0c;SSD的性能随着SSD的磨损的下降率为4.2%&#xff0c;吞吐量下降不太可能是由于垃圾收集造成的&#xff0c;因为&#xff08;1&#xff09;这是几个月来每天测量的&…

手写分布式配置中心(二)实现分布式配置中心的简单版本

这一篇文章比较简单&#xff0c;就是一个增删改查的服务端和一个获取配置的客户端&#xff0c;旨在搭建一个简单的配置中心架构&#xff0c;代码在 https://gitee.com/summer-cat001/config-center 服务端 服务端选择用springboot 2.7.14搭建&#xff0c;设计了4个接口/confi…

Guava处理异常

guava由Google开发&#xff0c;它提供了大量的核心Java库&#xff0c;例如&#xff1a;集合、缓存、原生类型支持、并发库、通用注解、字符串处理和I/O操作等。 异常处理 传统的Java异常处理通常包括try-catch-finally块和throws关键字。 遇到FileNotFoundException或IOExce…

49、WEB攻防——通用漏洞业务逻辑水平垂直越权访问控制脆弱验证

文章目录 前置知识点水平越权——YXCMS 前置知识点 逻辑越权原理&#xff1a; 水平越权&#xff1a;同级用户权限共享。用户信息获取时未对用户与ID比较判断直接查询等&#xff1b;垂直越权&#xff1a;低高级用户权限共享。数据库中用户类型编号接受篡改或高权限未作验证等。 …

Unity 使用AddListener监听事件与取消监听

在Unity中&#xff0c;有时候我们会动态监听组件中的某个事件。当我们使用代码动态加载多次&#xff0c;每次动态加载后我们会发现原来的和新的事件都会监听&#xff0c;如若我们只想取代原来的监听事件&#xff0c;那么就需要取消监听再添加监听了。 如实现如下需求&#xff…

一加 Ace 3 原神刻晴定制机首销现象级火爆,京东天猫双平台火速售罄

3 月 5 日上午 10 点&#xff0c;一加 Ace 3 原神刻晴定制机正式开售&#xff0c;京东天猫双平台火速售罄。一加 Ace 3 原神刻晴定制机以打造2024行业深度定制新标杆为目标&#xff0c;凭借行业首创工艺、典藏级限定周边、深度的系统定制以及专业的游戏表现&#xff0c;一经发布…

elementUI el-table中的对齐问题

用elementUI时&#xff0c;遇到了一个无法对齐的问题&#xff1a;代码如下&#xff1a; <el-table :data"form.dataList" <el-table-column label"验收结论" prop"checkResult" width"200"> <template slot-sco…

少儿编程 中国电子学会C++等级考试一级历年真题答案解析【持续更新 已更新82题】

C 等级考试一级考纲说明 一、能力目标 通过本级考核的学生&#xff0c;能对 C 语言有基本的了解&#xff0c;会使用顺序结构、选择结构、循环结构编写程序&#xff0c;具体用计算思维的方式解决简单的问题。 二、考核目标 考核内容是根据软件开发所需要的技能和知识&#x…

Premiere Pro 2024:革新视频编辑,打造专业影视新纪元

在数字化时代&#xff0c;视频已经成为人们获取信息、娱乐消遣的重要媒介。对于视频制作者而言&#xff0c;拥有一款功能强大、易于操作的视频编辑软件至关重要。Premiere Pro 2024&#xff0c;作为Adobe旗下的旗舰视频编辑软件&#xff0c;凭借其卓越的性能和创新的特性&#…

去中心化钱包应用:数字货币时代的自由与安全之选

​小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 随…