测试智能合约 test-smart-contracts

这个技能用于编写和执行Algorand智能合约的集成测试,包括设置测试环境、部署合约、调试测试问题以及模拟多用户交互场景。

智能合约 0 次安装 0 次浏览 更新于 3/4/2026

name: test-smart-contracts description: 测试Algorand智能合约的模式,使用生成的客户端和algorandFixture。在编写智能合约测试、设置测试固定装置和部署、调试失败的测试、测试多用户场景或询问E2E与单元测试时使用。强烈的触发词包括“我该如何测试我的合约”、“algorandFixture”、“测试失败”、“LocalNet测试”、“vitest设置”、“为合约提供资金”。

测试智能合约

使用algorandFixture和生成的类型化客户端编写Algorand智能合约的集成测试。

默认:集成测试(E2E)

**除非用户明确请求单元测试,否则始终编写集成测试。**集成测试针对LocalNet运行并测试真实的合约行为。

测试框架:支持Vitest(默认)和Jest。以下示例使用Vitest语法,但Jest等效物同样适用。

文件命名

  • 集成测试:contract.algo.e2e.spec.ts
  • 单元测试(仅在请求时):contract.algo.spec.ts

规范示例

学习和适应:devportal-code-examples/contracts/HelloWorld

import { Config } from '@algorandfoundation/algokit-utils'
import { algorandFixture } from '@algorandfoundation/algokit-utils/testing'
import { Address } from 'algosdk'
import { beforeAll, beforeEach, describe, expect, test } from 'vitest'
import { MyContractFactory } from '../artifacts/clients/MyContract/MyContractClient'

describe('MyContract', () => {
  const localnet = algorandFixture()

  beforeAll(() => {
    Config.configure({ debug: true })
  })
  // 10秒超时:LocalNet需要时间处理交易和确认区块
  beforeEach(localnet.newScope, 10_000)

  const deploy = async (account: Address) => {
    const factory = localnet.algorand.client.getTypedAppFactory(MyContractFactory, {
      defaultSender: account,
    })
    const { appClient } = await factory.deploy({
      onUpdate: 'append',
      onSchemaBreak: 'append',
      suppressLog: true,
    })
    return { client: appClient }
  }

  test('should call method and verify result', async () => {
    const { testAccount } = localnet.context
    const { client } = await deploy(testAccount)

    const result = await client.send.myMethod({ args: { value: 42n } })
    expect(result.return).toBe(42n)
  })
})

如何进行

  1. 定位生成的客户端artifacts/clients/<ContractName>/<ContractName>Client.ts
  2. 导入工厂(例如,MyContractFactory)- 不是直接导入客户端
  3. 使用部署助手模式 如上所示
  4. **通过 client.send.methodName()client.newGroup().methodName().send() 调用方法

重要规则

规则 详情
使用newGroup()进行链式操作 client.newGroup().method1().method2().send()
结构返回是元组 const [id, name] = result.return as [bigint, string]
为BoxMap提供资金 在box操作之前向client.appAddress发送支付
在本地状态之前选择加入 await client.newGroup().optIn.optInToApplication().send()

常见模式

为box存储提供资金给合约

await localnet.algorand.send.payment({
  amount: (1).algo(),
  sender: testAccount,
  receiver: client.appAddress,
})

同一合约上的多个用户

// 创建并为第二个用户提供资金
const user2 = localnet.algorand.account.random()
await localnet.algorand.send.payment({
  amount: (5).algo(),
  sender: testAccount,
  receiver: user2.addr,
})

// 使用不同的发送者获取相同应用程序的客户端
const client2 = factory.getAppClientById({
  appId: client.appId,
  defaultSender: user2.addr,
})

Box引用

import { ABIUintType } from 'algosdk'

function createBoxReference(appId: bigint, prefix: string, key: bigint) {
  const uint64Type = new ABIUintType(64)
  const encodedKey = uint64Type.encode(key)
  const boxName = new Uint8Array([...new TextEncoder().encode(prefix), ...encodedKey])
  return { appId, name: boxName }
}

await client.send.setBoxMap({
  args: { key: 1n, value: 'hello' },
  boxReferences: [createBoxReference(client.appId, 'boxMap', 1n)],
})

参考