Docs
Buscar⌘ K
  • Início
  • Sobre o The Graph
  • Redes Apoiadas
  • Contratos de Protocolo
  • Subgraphs
    • Substreams
      • Token API
        • AI Suite
          • Indexação
            • Recursos
              Subgraphs > Programação > Criação

              26 minutos

              Estrutura de Testes de Unidades

              Learn how to use Matchstick, a unit testing framework developed by LimeChain⁠. Matchstick enables Subgraph developers to test their mapping logic in a sandboxed environment and successfully deploy their Subgraphs.

              Vantagens de Usar o Matchstick

              • É escrito em Rust e otimizado para o melhor desempenho possível.
              • It gives you access to developer features, including the ability to mock contract calls, make assertions about the store state, monitor Subgraph failures, check test performance, and many more.

              Como Começar

              Como Instalar Dependências

              Para usar os métodos de test helper e executar os testes, instale as seguintes dependências:

              1yarn add --dev matchstick-as

              Como Instalar o PostgreSQL

              O graph-node depende do PostgreSQL, então se ainda não o tem, será necessário instalá-lo.

              Observação: É altamente recomendável usar os comandos abaixo para evitar erros inesperados.

              Usando o MacOS

              Comando de instalação:

              1brew install postgresql

              Crie um symlink ao último libpq.5.lib Talvez precise criar este diretório primeiro: /usr/local/opt/postgresql/lib/

              1ln -sf /usr/local/opt/postgresql@14/lib/postgresql@14/libpq.5.dylib /usr/local/opt/postgresql/lib/libpq.5.dylib

              Usando o Linux

              Comando de instalação do Postgres (depende da sua distro):

              1sudo apt install postgresql

              Usando o WSL (Subsistema do Windows para o Linux)

              Pode usar o Matchstick no WSL tanto com a abordagem do Docker quanto com a abordagem binária. Como o WSL pode ser um pouco complicado, aqui estão algumas dicas caso encontre problemas

              1static BYTES = Symbol("Bytes") SyntaxError: Unexpected token =

              ou

              1<PROJECT_PATH>/node_modules/gluegun/build/index.js:13 throw up;

              Verifique se está em uma versão mais recente do Node.js. O graph-cli não apoia mais a v10.19.0, que ainda é a versão padrão para novas imagens de Ubuntu no WSL. Por exemplo, se o Matchstick é confirmado como funcional no WSL com a v18.1.0, pode trocar para essa versão através do nvm ou ao atualizar o seu Node.js global. Não se esqueça de apagar o node_modules e executar o npm install novamente após atualizar o seu nodejs! Depois, garanta que tem o libpq instalado. Isto pode ser feito ao executar:

              1sudo apt-get install libpq-dev

              E finalmente, não use o graph test (que usa a sua instalação global da graph-cli, e por alguma razão, parece não funcionar no WSL no momento). Em vez disto, use o yarn test ou o npm run test (que usará a instância local do graph-cli; esta funciona muito bem). Para isto, obviamente você precisa de um script "test" no seu arquivo package.json, que pode ser algo simples como

              1{2  "name": "demo-subgraph",3  "version": "0.1.0",4  "scripts": {5    "test": "graph test",6    ...7  },8  "dependencies": {9    "@graphprotocol/graph-cli": "^0.56.0",10    "@graphprotocol/graph-ts": "^0.31.0",11    "matchstick-as": "^0.6.0"12  }13}

              Usando o Matchstick

              To use Matchstick in your Subgraph project just open up a terminal, navigate to the root folder of your project and simply run graph test [options] <datasource> - it downloads the latest Matchstick binary and runs the specified test or all tests in a test folder (or all existing tests if no datasource flag is specified).

              Opções de CLI

              Isto executará todos os testes na pasta-teste:

              1graph test

              Isto executará um teste chamado gravity.test.ts e/ou todos os testes dentro de uma pasta chamada gravity:

              1graph test gravity

              Isto só executará esse arquivo de teste específico:

              1graph test path/to/file.test.ts

              Opções:

              1-c, --coverage                Run the tests in coverage mode2-d, --docker                  Run the tests in a docker container (Note: Please execute from the root folder of the Subgraph)3-f, --force                   Binary: Redownloads the binary. Docker: Redownloads the Dockerfile and rebuilds the docker image.4-h, --help                    Show usage information5-l, --logs                    Logs to the console information about the OS, CPU model and download url (debugging purposes)6-r, --recompile               Forces tests to be recompiled7-v, --version <tag>           Choose the version of the rust binary that you want to be downloaded/used

              Docker

              Desde o graph-cli 0.25.2, o comando graph test apoia a execução do matchstick em um container docker com a flag -d. A implementação do docker utiliza o bind mount⁠ para que não precise reconstruir a imagem do docker toda vez que o comando graph test -d for executado. Alternativamente, siga as instruções do repositório do matchstick⁠ para executar o docker manualmente.

              ❗ graph test -d força o docker run a ser executado com o flag -t. Isto deve ser removido para rodar em ambientes não interativos (como o GitHub CI).

              ❗ Caso já tenha executado o graph test anteriormente, o seguinte erro pode aparecer durante a compilação do docker:

              1error from sender: failed to xattr node_modules/binary-install-raw/bin/binary-<platform>: permission denied

              Neste caso, crie um .dockerignore na pasta raiz e adicione node_modules/binary-install-raw/bin

              Configuração

              O Matchstick pode ser configurado para usar um caminho personalizado de tests, libs e manifest através do arquivo de configuração matchstick.yaml:

              1testsFolder: path/to/tests2libsFolder: path/to/libs3manifestPath: path/to/subgraph.yaml

              Demo Subgraph

              Você pode experimentar com os exemplos deste guia clonando o repositório de Subgraph Demonstrativo⁠

              Tutoriais de vídeo

              Also you can check out the video series on “How to use Matchstick to write unit tests for your Subgraphs”⁠

              Estrutura de testes

              IMPORTANT: The test structure described below depends on matchstick-as version >=0.5.0

              describe()

              describe(name: String , () = {}) — Define um grupo de teste.

              Observações:

              • Describes (descrições) não são obrigatórias. O test() ainda pode ser usado da maneira antiga, fora dos blocos describe()

              Exemplo:

              1import { describe, test } from "matchstick-as/assembly/index"2import { handleNewGravatar } from "../../src/gravity"34describe("handleNewGravatar()", () => {5  test("Isto deve criar uma nova entidade Gravatar", () => {6    ...7  })8})

              Exemplo aninhado de describe():

              1import { describe, test } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar } from "../../src/gravity"34describe("handleUpdatedGravatar()", () => {5  describe("Quando houver uma entidade", () => {6    test("entidade atualizada", () => {7      ...8    })9  })1011  describe("Quando não houver uma entidade", () => {12    test("nova entidade criada", () => {13      ...14    })15  })16})

              test()

              test(name: String, () =, should_fail: bool) — Define um caso de teste. O test() pode ser usado em blocos describe() ou de maneira independente.

              Exemplo:

              1import { describe, test } from "matchstick-as/assembly/index"2import { handleNewGravatar } from "../../src/gravity"34describe("handleNewGravatar()", () => {5  test("Isto deve criar uma nova Entidade", () => {6    ...7  })8})

              ou

              1test("handleNewGravatar() deve criar uma nova entidade", () => {2  ...3})

              beforeAll()

              Executa um bloco de código antes de quaisquer dos testes no arquivo. Se o beforeAll for declarado dentro de um bloco describe, ele é executado no começo daquele bloco describe.

              Exemplos:

              O código dentro do beforeAll será executado uma vez antes de todos os testes no arquivo.

              1import { describe, test, beforeAll } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity"3import { Gravatar } from "../../generated/schema"45beforeAll(() => {6  let gravatar = new Gravatar("0x0")7  gravatar.displayName = “First Gravatar”8  gravatar.save()9  ...10})1112describe("Quando a entidade não existe", () => {13  test("ela deve criar um novo Gravatar com a id 0x1", () => {14    ...15  })16})1718describe("Quando a entidade já existe", () => {19  test("ela deve atualizar o Gravatar com a id 0x0", () => {20    ...21  })22})

              O código antes do beforeAll será executado uma vez antes de todos os testes no primeiro bloco describe

              1mport { describe, test, beforeAll } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity"3import { Gravatar } from "../../generated/schema"45describe("handleUpdatedGravatar()", () => {6  beforeAll(() => {7    let gravatar = new Gravatar("0x0")8    gravatar.displayName = “Primeiro Gravatar”9    gravatar.save()10    ...11  })1213  test("atualiza Gravatar com id 0x0", () => {14    ...15  })1617  test("cria novo Gravatar com id 0x1", () => {18    ...19  })20})

              afterAll()

              Executa um bloco de código depois de todos os testes no arquivo. Se o afterAll for declarado dentro de um bloco describe, ele será executado no final desse bloco describe.

              Exemplo:

              O código dentro do afterAll será executado uma vez depois de todos os testes no arquivo.

              1import { describe, test, afterAll } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity"3import { store } from "@graphprotocol/graph-ts"45afterAll(() => {6  store.remove("Gravatar", "0x0")7  ...8})910describe("handleNewGravatar, () => {11  test("cria Gravatar com id 0x0", () => {12    ...13  })14})1516describe("handleUpdatedGravatar", () => {17  test("atualiza Gravatar com id 0x0", () => {18    ...19  })20})

              O código dentro do afterAll será executado uma vez depois de todos os testes no primeiro bloco describe

              1import { describe, test, afterAll, clearStore } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity"34describe("handleNewGravatar", () => {5	afterAll(() => {6    store.remove("Gravatar", "0x1")7    ...8	})910  test("Cria uma nova entidade com Id 0x0", () => {11    ...12  })1314  test("Cria uma nova entidade com Id 0x1", () => {15    ...16  })17})1819describe("handleUpdatedGravatar", () => {20  test("atualiza Gravatar com id 0x0", () => {21    ...22  })23})

              beforeEach()

              Executa um bloco de código antes de cada teste no arquivo. Se o beforeEach for declarado dentro de um bloco describe, ele será executado antes de cada teste nesse bloco describe.

              Exemplos: O código dentro do beforeEach será executado antes de cada teste.

              1import { describe, test, beforeEach, clearStore } from "matchstick-as/assembly/index"2import { handleNewGravatars } from "./utils"34beforeEach(() => {5  clearStore() // <-- limpa o armazenamento antes de cada teste no arquivo6})78describe("handleNewGravatars, () => {9  test("Teste que exige armazenamento limpo", () => {10    ...11  })1213  test("Segundo que exige armazenamento limpo", () => {14    ...15  })16})1718 ...

              O código antes do beforeEach será executado antes de cada teste no describe

              1import { describe, test, beforeEach } from 'matchstick-as/assembly/index'2import { handleUpdatedGravatar, handleNewGravatar } from '../../src/gravity'34describe('handleUpdatedGravatars', () => {5  beforeEach(() => {6    let gravatar = new Gravatar('0x0')7    gravatar.displayName = 'Primeiro Gravatar'8    gravatar.imageUrl = ''9    gravatar.save()10  })1112  test('Atualiza o displayName', () => {13    assert.fieldEquals('Gravatar', '0x0', 'displayName', 'Primeiro Gravatar')1415    // código que deve atualizar o displayName para 1o. Gravatar1617    assert.fieldEquals('Gravatar', '0x0', 'displayName', '1o. Gravatar')18    store.remove('Gravatar', '0x0')19  })2021  test('Atualiza o imageUrl', () => {22    assert.fieldEquals('Gravatar', '0x0', 'imageUrl', '')2324    // código que deve mudar imageUrl para https://www.gravatar.com/avatar/0x02526    assert.fieldEquals('Gravatar', '0x0', 'imageUrl', 'https://www.gravatar.com/avatar/0x0')27    store.remove('Gravatar', '0x0')28  })29})

              afterEach()

              Executa um bloco de código depois de cada teste no arquivo. Se o afterEach for declarado dentro de um bloco describe, será executado após cada teste nesse describe.

              Exemplos:

              O código dentro do afterEach será executado após cada teste.

              1import { describe, test, beforeEach, afterEach } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity"34beforeEach(() => {5  let gravatar = new Gravatar("0x0")6  gravatar.displayName = “Primeiro Gravatar”7  gravatar.save()8})910afterEach(() => {11  store.remove("Gravatar", "0x0")12})1314describe("handleNewGravatar", () => {15  ...16})1718describe("handleUpdatedGravatar", () => {19  test("Atualiza o displayName", () => {20     assert.fieldEquals("Gravatar", "0x0", "displayName", "Primeiro Gravatar")2122    // código que deve mudar o displayName para 1o. Gravatar2324    assert.fieldEquals("Gravatar", "0x0", "displayName", "1o. Gravatar")25  })2627  test("Atualiza o imageUrl", () => {28    assert.fieldEquals("Gravatar", "0x0", "imageUrl", "")2930    // código que deve mudar o imageUrl para https://www.gravatar.com/avatar/0x03132    assert.fieldEquals("Gravatar", "0x0", "imageUrl", "https://www.gravatar.com/avatar/0x0")33  })34})

              O código dentro do afterEach será executado após cada teste nesse describe

              1import { describe, test, beforeEach, afterEach } from "matchstick-as/assembly/index"2import { handleUpdatedGravatar, handleNewGravatar } from "../../src/gravity"34describe("handleNewGravatar", () => {5  ...6})78describe("handleUpdatedGravatar", () => {9  beforeEach(() => {10    let gravatar = new Gravatar("0x0")11    gravatar.displayName = "Primeiro Gravatar"12    gravatar.imageUrl = ""13    gravatar.save()14  })1516  afterEach(() => {17    store.remove("Gravatar", "0x0")18  })1920  test("Updates the displayName", () => {21     assert.fieldEquals("Gravatar", "0x0", "displayName", "Primeiro Gravatar")2223    // código que deve atualizar o displayName para 1o. Gravatar2425    assert.fieldEquals("Gravatar", "0x0", "displayName", "1o. Gravatar")26  })2728  test("Updates the imageUrl", () => {29    assert.fieldEquals("Gravatar", "0x0", "imageUrl", "")3031    // código que deve mudar o imageUrl para https://www.gravatar.com/avatar/0x03233    assert.fieldEquals("Gravatar", "0x0", "imageUrl", "https://www.gravatar.com/avatar/0x0")34  })35})

              Asserts

              1fieldEquals(entityType: string, id: string, fieldName: string, expectedVal: string)23equals(expected: ethereum.Value, actual: ethereum.Value)45notInStore(entityType: string, id: string)67addressEquals(address1: Address, address2: Address)89bytesEquals(bytes1: Bytes, bytes2: Bytes)1011i32Equals(number1: i32, number2: i32)1213bigIntEquals(bigInt1: BigInt, bigInt2: BigInt)1415booleanEquals(bool1: boolean, bool2: boolean)1617stringEquals(string1: string, string2: string)1819arrayEquals(array1: Array<ethereum.Value>, array2: Array<ethereum.Value>)2021tupleEquals(tuple1: ethereum.Tuple, tuple2: ethereum.Tuple)2223assertTrue(value: boolean)2425assertNull<T>(value: T)2627assertNotNull<T>(value: T)2829entityCount(entityType: string, expectedCount: i32)

              A partir da versão 0.6.0, asserts também apoiam mensagens de erro personalizadas

              1assert.fieldEquals('Gravatar', '0x123', 'id', '0x123', 'Id deve ser 0x123')2assert.equals(ethereum.Value.fromI32(1), ethereum.Value.fromI32(1), 'Valor deve ser igual a 1')3assert.notInStore('Gravatar', '0x124', 'Gravatar não deve estar armazenado')4assert.addressEquals(Address.zero(), Address.zero(), 'Address deve ser zero')5assert.bytesEquals(Bytes.fromUTF8('0x123'), Bytes.fromUTF8('0x123'), 'Bytes devem ser iguais')6assert.i32Equals(2, 2, 'I32 deve ser igual a 2')7assert.bigIntEquals(BigInt.fromI32(1), BigInt.fromI32(1), 'BigInt deve ser igual 1')8assert.booleanEquals(true, true, 'Boolean deve ser true')9assert.stringEquals('1', '1', 'String deve ser igual a 1')10assert.arrayEquals([ethereum.Value.fromI32(1)], [ethereum.Value.fromI32(1)], 'Arranjos devem ser iguais')11assert.tupleEquals(12  changetype<ethereum.Tuple>([ethereum.Value.fromI32(1)]),13  changetype<ethereum.Tuple>([ethereum.Value.fromI32(1)]),14  'Tuplas devem ser iguais',15)16assert.assertTrue(true, 'Deve ser true')17assert.assertNull(null, 'Deve ser null')18assert.assertNotNull('not null', 'Deve não ser null')19assert.entityCount('Gravatar', 1, 'Deve haver 2 Gravatars')20assert.dataSourceCount('GraphTokenLockWallet', 1, 'Template GraphTokenLockWallet template deve ter uma fonte de dados')21assert.dataSourceExists(22  'GraphTokenLockWallet',23  Address.zero().toHexString(),24  'GraphTokenLockWallet deve ter uma fonte de dados para address zero',25)

              Como Escrever um Teste de Unidade

              Vamos ver como seria um simples teste unitário usando os exemplos de Gravatar no Subgraph de Demonstração⁠.

              Suponhamos que temos a seguinte função de handler (com duas funções de helper para facilitar):

              1export function handleNewGravatar(event: NewGravatar): void {2  let gravatar = new Gravatar(event.params.id.toHex())3  gravatar.owner = event.params.owner4  gravatar.displayName = event.params.displayName5  gravatar.imageUrl = event.params.imageUrl6  gravatar.save()7}89export function handleNewGravatars(events: NewGravatar[]): void {10  events.forEach((event) => {11    handleNewGravatar(event)12  })13}1415export function createNewGravatarEvent(16  id: i32,17  ownerAddress: string,18  displayName: string,19  imageUrl: string,20): NewGravatar {21  let mockEvent = newMockEvent()22  let newGravatarEvent = new NewGravatar(23    mockEvent.address,24    mockEvent.logIndex,25    mockEvent.transactionLogIndex,26    mockEvent.logType,27    mockEvent.block,28    mockEvent.transaction,29    mockEvent.parameters,30  )31  newGravatarEvent.parameters = new Array()32  let idParam = new ethereum.EventParam('id', ethereum.Value.fromI32(id))33  let addressParam = new ethereum.EventParam(34    'ownerAddress',35    ethereum.Value.fromAddress(Address.fromString(ownerAddress)),36  )37  let displayNameParam = new ethereum.EventParam('displayName', ethereum.Value.fromString(displayName))38  let imageUrlParam = new ethereum.EventParam('imageUrl', ethereum.Value.fromString(imageUrl))3940  newGravatarEvent.parameters.push(idParam)41  newGravatarEvent.parameters.push(addressParam)42  newGravatarEvent.parameters.push(displayNameParam)43  newGravatarEvent.parameters.push(imageUrlParam)4445  return newGravatarEvent46}

              Primeiro, devemos criar um arquivo de teste no nosso projeto. Este é um exemplo de como ele pode ficar:

              1import { clearStore, test, assert } from 'matchstick-as/assembly/index'2import { Gravatar } from '../../generated/schema'3import { NewGravatar } from '../../generated/Gravity/Gravity'4import { createNewGravatarEvent, handleNewGravatars } from '../mappings/gravity'56test('Can call mappings with custom events', () => {7  // Criar uma entidade de teste e guarda no armazenamento como estado inicial (opcional)8  let gravatar = new Gravatar('gravatarId0')9  gravatar.save()1011  // Criar eventos simulados12  let newGravatarEvent = createNewGravatarEvent(12345, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac')13  let anotherGravatarEvent = createNewGravatarEvent(3546, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac')1415  // Chamar funções de mapeamento passando os eventos que acabamos de criar16  handleNewGravatars([newGravatarEvent, anotherGravatarEvent])1718  // Assertar o estado do armazenamento19  assert.fieldEquals('Gravatar', 'gravatarId0', 'id', 'gravatarId0')20  assert.fieldEquals('Gravatar', '12345', 'owner', '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7')21  assert.fieldEquals('Gravatar', '3546', 'displayName', 'cap')2223  // Limpar o armazenamento para começar o próximo teste do zero24  clearStore()25})2627test('Next test', () => {28  //...29})

              Quanta coisa! Primeiro, note que estamos a importar coisas do matchstick-as, a nossa biblioteca de helper do AssemblyScript (distribuída como um módulo npm). O repositório está aqui⁠. O matchstick-as nos dá alguns métodos de teste úteis e define a função test(), que usaremos para construir os nossos blocos de teste. O resto é bem simples — veja o que acontece:

              • Configuramos nosso estado inicial e adicionamos uma entidade de Gravatar personalizada;
              • Definimos dois eventos NewGravatar com os seus dados, usando a função createNewGravatarEvent();
              • Chamamos métodos de handlers para estes eventos — handleNewGravatars() — e passamos a lista dos nossos eventos personalizados;
              • Garantimos o estado da loja. Como isto funciona? — Passamos uma combinação do tipo e da id da Entidade. Depois conferimos um campo específico naquela Entidade e garantimos que ela tem o valor que esperamos que tenha. Estamos a fazer isto tanto para a Entidade Gravatar inicial adicionada ao armazenamento, quanto para as duas entidades Gravatar adicionadas ao chamar a função de handler;
              • E por último — limpamos o armazenamento com clearStore(), para que o nosso próximo teste comece com um objeto de armazenamento novo em folha. Podemos definir quantos blocos de teste quisermos.

              Prontinho — criamos o nosso primeiro teste! 👏

              Now in order to run our tests you simply need to run the following in your Subgraph root folder:

              graph test Gravity

              E se tudo der certo, deve receber a seguinte resposta:

              Matchstick diz "Todos os testes passados!”

              Cenários de teste comuns

              Como hidratar o armazenamento com um certo estado

              Os utilizadores podem hidratar o armazenamento com um conjunto conhecido de entidades. Aqui está um exemplo para inicializar o armazenamento com uma entidade Gravatar:

              1let gravatar = new Gravatar('entryId')2gravatar.save()

              Como chamar uma função de mapeamento com um evento

              Um utilizador pode criar um evento personalizado e passá-lo a uma função de mapeamento ligada ao armazenamento:

              1import { store } from 'matchstick-as/assembly/store'2import { NewGravatar } from '../../generated/Gravity/Gravity'3import { handleNewGravatars, createNewGravatarEvent } from './mapping'45let newGravatarEvent = createNewGravatarEvent(12345, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac')67handleNewGravatar(newGravatarEvent)

              Como chamar todos os mapeamentos com fixações de eventos

              Os utilizadores podem chamar os mapeamentos com fixações de teste.

              1import { NewGravatar } from '../../generated/Gravity/Gravity'2import { store } from 'matchstick-as/assembly/store'3import { handleNewGravatars, createNewGravatarEvent } from './mapping'45let newGravatarEvent = createNewGravatarEvent(12345, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac')67let anotherGravatarEvent = createNewGravatarEvent(3546, '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7', 'cap', 'pac')89handleNewGravatars([newGravatarEvent, anotherGravatarEvent])
              1export function handleNewGravatars(events: NewGravatar[]): void {2    events.forEach(event => {3        handleNewGravatar(event);4    });5}

              Como simular chamadas de contratos

              Os utilizadores podem simular chamadas de contratos:

              1import { addMetadata, assert, createMockedFunction, clearStore, test } from 'matchstick-as/assembly/index'2import { Gravity } from '../../generated/Gravity/Gravity'3import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'45let contractAddress = Address.fromString('0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7')6let expectedResult = Address.fromString('0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947')7let bigIntParam = BigInt.fromString('1234')8createMockedFunction(contractAddress, 'gravatarToOwner', 'gravatarToOwner(uint256):(address)')9  .withArgs([ethereum.Value.fromSignedBigInt(bigIntParam)])10  .returns([ethereum.Value.fromAddress(Address.fromString('0x90cBa2Bbb19ecc291A12066Fd8329D65FA1f1947'))])1112let gravity = Gravity.bind(contractAddress)13let result = gravity.gravatarToOwner(bigIntParam)1415assert.equals(ethereum.Value.fromAddress(expectedResult), ethereum.Value.fromAddress(result))

              Como demonstrado, para simular uma chamada de contrato e conseguir um valor de retorno de linha-dura, o utilizador deve fornecer um endereço de contrato, nome de função, assinatura de função, arranjo de argumentos — e claro, o valor de retorno.

              Os utilizadores também podem simular regressos de funções:

              1let contractAddress = Address.fromString('0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7')2createMockedFunction(contractAddress, 'getGravatar', 'getGravatar(address):(string,string)')3  .withArgs([ethereum.Value.fromAddress(contractAddress)])4  .reverts()

              Como simular arquivos IPFS (do matchstick 0.4.1)

              Os utilizadores podem simular arquivos IPFS com a função mockIpfsFile(hash, filePath). A função aceita dois argumentos: o primeiro é o hash/caminho do arquivo IPFS, e o segundo é o caminho a um arquivo local.

              NOTE: When testing ipfs.map/ipfs.mapJSON, the callback function must be exported from the test file in order for matchstick to detect it, like the processGravatar() function in the test example bellow:

              Arquivo test.ts:

              1import { assert, test, mockIpfsFile } from 'matchstick-as/assembly/index'2import { ipfs } from '@graphprotocol/graph-ts'3import { gravatarFromIpfs } from './utils'45// Export ipfs.map() callback in order for matchstick to detect it6export { processGravatar } from './utils'78test('ipfs.cat', () => {9  mockIpfsFile('ipfsCatfileHash', 'tests/ipfs/cat.json')1011  assert.entityCount(GRAVATAR_ENTITY_TYPE, 0)1213  gravatarFromIpfs()1415  assert.entityCount(GRAVATAR_ENTITY_TYPE, 1)16  assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '1', 'imageUrl', 'https://i.ytimg.com/vi/MELP46s8Cic/maxresdefault.jpg')1718  clearStore()19})2021test('ipfs.map', () => {22  mockIpfsFile('ipfsMapfileHash', 'tests/ipfs/map.json')2324  assert.entityCount(GRAVATAR_ENTITY_TYPE, 0)2526  ipfs.map('ipfsMapfileHash', 'processGravatar', Value.fromString('Gravatar'), ['json'])2728  assert.entityCount(GRAVATAR_ENTITY_TYPE, 3)29  assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '1', 'displayName', 'Gravatar1')30  assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '2', 'displayName', 'Gravatar2')31  assert.fieldEquals(GRAVATAR_ENTITY_TYPE, '3', 'displayName', 'Gravatar3')32})

              Arquivo utils.ts:

              1import { Address, ethereum, JSONValue, Value, ipfs, json, Bytes } from "@graphprotocol/graph-ts"2import { Gravatar } from "../../generated/schema"34...56// callback do ipfs.map7export function processGravatar(value: JSONValue, userData: Value): void {8  // See the JSONValue documentation for details on dealing9  // with JSON values10  let obj = value.toObject()11  let id = obj.get('id')1213  if (!id) {14    return15  }1617  // Callbacks também podem criar entidades18  let gravatar = new Gravatar(id.toString())19  gravatar.displayName = userData.toString() + id.toString()20  gravatar.save()21}2223// função que chama o ipfs.cat24export function gravatarFromIpfs(): void {25  let rawData = ipfs.cat("ipfsCatfileHash")2627  if (!rawData) {28    return29  }3031  let jsonData = json.fromBytes(rawData as Bytes).toObject()3233  let id = jsonData.get('id')34  let url = jsonData.get("imageUrl")3536  if (!id || !url) {37    return38  }3940  let gravatar = new Gravatar(id.toString())41  gravatar.imageUrl = url.toString()42  gravatar.save()43}

              Como afirmar o estado do armazenamento

              Os utilizadores podem afirmar o estado final (ou parcial) do armazenamento através de entidades de afirmação. Para isto, o utilizador precisa fornecer um tipo de Entidade, a ID específica de uma Entidade, o nome de um campo naquela Entidade, e o valor esperado do campo. Aqui vai um exemplo rápido:

              1import { assert } from 'matchstick-as/assembly/index'2import { Gravatar } from '../generated/schema'34let gravatar = new Gravatar('gravatarId0')5gravatar.save()67assert.fieldEquals('Gravatar', 'gravatarId0', 'id', 'gravatarId0')

              A função assert.fieldEquals() conferirá a igualdade do campo dado contra o valor dado esperado. O teste acabará em erro, com mensagem correspondente, caso os valores NÃO sejam iguais. Caso contrário, o teste terá êxito.

              Como interagir com metadados de Eventos

              Os utilizadores podem usar metadados-padrão de transações, que podem ser retornados como um ethereum.Event com a função newMockEvent(). O seguinte exemplo mostra como podes ler/escrever a estes campos no objeto de Evento:

              1// Leitura2let logType = newGravatarEvent.logType34// Escrita5let UPDATED_ADDRESS = '0xB16081F360e3847006dB660bae1c6d1b2e17eC2A'6newGravatarEvent.address = Address.fromString(UPDATED_ADDRESS)

              Como afirmar a igualdade das variáveis

              1assert.equals(ethereum.Value.fromString("hello"); ethereum.Value.fromString("hello"));

              Como afirmar que uma Entidade não está no armazenamento

              Os utilizadores podem afirmar que uma entidade não existe no armazenamento. A função toma um tipo e uma id de entidade. Caso a entidade esteja, de facto, na loja, o teste acabará em erro, com uma mensagem de erro relevante. Veja um exemplo rápido de como usar esta funcionalidade:

              1assert.notInStore('Gravatar', '23')

              Impressão do armazenamento completo, ou de entidades individuais dele (para debugging)

              Pode imprimir o armazenamento inteiro na consola com esta função de helper:

              1import { logStore } from 'matchstick-as/assembly/store'23logStore()

              Desde a versão 0.6.0, o logStore não imprime mais campos derivados; em vez disto, os utilizadores podem usar a nova função logEntity. O logEntity pode ser usado para imprimir qualquer entidade, não só as que têm campos derivados. O logEntity pega o tipo e a ID da entidade, e um flag showRelated para indicar se os utilizadores querem imprimir as entidades derivadas relacionadas.

              1import { logEntity } from 'matchstick-as/assembly/store'234logEntity("Gravatar", 23, true)

              Falhas esperadas

              Os utilizadores podem encontrar falhas esperadas, com o flag shouldFail nas funções test():

              1test(2  'Deve chamar um erro',3  () => {4    throw new Error()5  },6  true,7)

              Caso o teste seja marcado com shouldFail = true mas NÃO falhe, isto será mostrado como um erro nos logs e o bloco de teste não terá êxito. E se for marcado com shouldFail = false (o estado normal), o executor de teste travará.

              Logging

              Ter logs personalizados nos testes de unidade é a mesma coisa que logar nos mapeamentos. A diferença é que o objeto do log deve ser importado do matchstick-as, em vez do graph-ts. Aqui vai um exemplo simples com todos os tipos de log não-críticos:

              1import { test } from "matchstick-as/assembly/index";2import { log } from "matchstick-as/assembly/log";34test("Success", () => {5    log.success("Sucesso!". []);6});7test("Error", () => {8    log.error("Erro! :( ", []);9});10test("Debug", () => {11    log.debug("Debug em progresso...", []);12});13test("Info", () => {14    log.info("Informação!", []);15});16test("Warning", () => {17    log.warning("Cuidado!", []);18});

              Os utilizadores também podem simular uma falha crítica, como no seguinte:

              1test('Explodir tudo', () = {2  log.critical('É boooomba!')3})

              Logar erros críticos interromperá a execução dos testes e causará um desastre. Afinal, queremos ter certeza que o seu código não tenha logs críticos no lançamento; perceberia imediatamente se isto acontecer.

              Como testar campos derivados

              Testar campos derivados permite aos utilizadores configurar um campo numa entidade e atualizar outra automaticamente, caso ela derive um dos seus campos da primeira entidade.

              Antes da versão 0.6.0, era possível resgatar as entidades derivadas ao acessá-las como propriedades ou campos de entidade, como no seguinte exemplo:

              1let entity = ExampleEntity.load('id')2let derivedEntity = entity.derived_entity

              Desde a versão 0.6.0, isto é feito com a função loadRelated do graph-node. As entidades derivadas podem ser acessadas como são nos handlers.

              1test('Derived fields example test', () => {2  let mainAccount = GraphAccount.load('12')!34  assert.assertNull(mainAccount.get('nameSignalTransactions'))5  assert.assertNull(mainAccount.get('operatorOf'))67  let operatedAccount = GraphAccount.load('1')!8  operatedAccount.operators = [mainAccount.id]9  operatedAccount.save()1011  mockNameSignalTransaction('1234', mainAccount.id)12  mockNameSignalTransaction('2', mainAccount.id)1314  mainAccount = GraphAccount.load('12')!1516  assert.assertNull(mainAccount.get('nameSignalTransactions'))17  assert.assertNull(mainAccount.get('operatorOf'))1819  const nameSignalTransactions = mainAccount.nameSignalTransactions.load()20  const operatorsOfMainAccount = mainAccount.operatorOf.load()2122  assert.i32Equals(2, nameSignalTransactions.length)23  assert.i32Equals(1, operatorsOfMainAccount.length)2425  assert.stringEquals('1', operatorsOfMainAccount[0].id)2627  mockNameSignalTransaction('2345', mainAccount.id)2829  let nst = NameSignalTransaction.load('1234')!30  nst.signer = '11'31  nst.save()3233  store.remove('NameSignalTransaction', '2')3435  mainAccount = GraphAccount.load('12')!36  assert.i32Equals(1, mainAccount.nameSignalTransactions.load().length)37})

              Teste de loadInBlock

              Desde a versão 0.6.0, é possível testar o loadInBlock com o mockInBlockStore, que permite a simulação de entidades no cache de blocos.

              1import { afterAll, beforeAll, describe, mockInBlockStore, test } from 'matchstick-as'2import { Gravatar } from '../../generated/schema'34describe('loadInBlock', () => {5  beforeAll(() => {6    mockInBlockStore('Gravatar', 'gravatarId0', gravatar)7  })89  afterAll(() => {10    clearInBlockStore()11  })1213  test('Pode usar entity.loadInBlock() para retirar a entidade do armazenamento do cache no bloco atual', () => {14    let retrievedGravatar = Gravatar.loadInBlock('gravatarId0')15    assert.stringEquals('gravatarId0', retrievedGravatar!.get('id')!.toString())16  })1718  test('Retorna null ao chamar entity.loadInBlock() se uma entidade não existir no bloco atual', () => {19    let retrievedGravatar = Gravatar.loadInBlock('IDoNotExist')20    assert.assertNull(retrievedGravatar)21  })22})

              Como testar fontes de dados dinâmicas

              É possível testar fontes de dados dinâmicas ao simular o valor de retorno das funções context(), address() e network() do namespace do dataSource. Estas funções atualmente retornam o seguinte: context() — retorna uma entidade vazia (DataSourceContext); address() — retorna 0x0000000000000000000000000000000000000000; network() — retorna mainnet. As funções create(...) e createWithContext(...) são simuladas para não terem uso, para que não precisem ser chamadas nos testes. Dá para mudar os valores de retorno através das funções do namespace dataSourceMock no matchstick-as (versão 0.3.0+).

              Exemplo abaixo:

              Primeiro temos o seguinte handler de eventos (que foi apropriado intencionalmente para demonstrar a falsificação de fontes de dados):

              1export function handleApproveTokenDestinations(event: ApproveTokenDestinations): void {2  let tokenLockWallet = TokenLockWallet.load(dataSource.address().toHexString())!3  if (dataSource.network() == 'rinkeby') {4    tokenLockWallet.tokenDestinationsApproved = true5  }6  let context = dataSource.context()7  if (context.get('contextVal')!.toI32() > 0) {8    tokenLockWallet.setBigInt('tokensReleased', BigInt.fromI32(context.get('contextVal')!.toI32()))9  }10  tokenLockWallet.save()11}

              E então, temos o teste que usa um dos métodos do namespace dataSourceMock para determinar um novo valor de retorno para todas as funções do dataSource:

              1import { assert, test, newMockEvent, dataSourceMock } from 'matchstick-as/assembly/index'2import { BigInt, DataSourceContext, Value } from '@graphprotocol/graph-ts'34import { handleApproveTokenDestinations } from '../../src/token-lock-wallet'5import { ApproveTokenDestinations } from '../../generated/templates/GraphTokenLockWallet/GraphTokenLockWallet'6import { TokenLockWallet } from '../../generated/schema'78test('Exemplo simples de simulação de fonte de dados', () => {9  let addressString = '0xA16081F360e3847006dB660bae1c6d1b2e17eC2A'10  let address = Address.fromString(addressString)1112  let wallet = new TokenLockWallet(address.toHexString())13  wallet.save()14  let context = new DataSourceContext()15  context.set('contextVal', Value.fromI32(325))16  dataSourceMock.setReturnValues(addressString, 'rinkeby', context)17  let event = changetype<ApproveTokenDestinations>(newMockEvent())1819  assert.assertTrue(!wallet.tokenDestinationsApproved)2021  handleApproveTokenDestinations(event)2223  wallet = TokenLockWallet.load(address.toHexString())!24  assert.assertTrue(wallet.tokenDestinationsApproved)25  assert.bigIntEquals(wallet.tokensReleased, BigInt.fromI32(325))2627  dataSourceMock.resetValues()28})

              Note que o dataSourceMock.resetValues() é chamado no final. Isto é porque os valores são lembrados quando mudados, e devem ser reconfigurados caso queira voltar aos valores padrão.

              Teste de criação de fontes de dados dinâmicas

              Desde a versão 0.6.0, é possível testar se uma nova fonte de dados foi criada de um modelo. Esta função apoia modelos ethereum/contract e file/ipfs. Há quatro funçôes para isto:

              • assert.dataSourceCount(templateName, expectedCount) pode ser usado para impor a contagem esperada de fontes de dados do modelo especificado
              • assert.dataSourceExists(templateName, address/ipfsHash) impõe que foi criada uma fonte de dados com o identificador especificado (seja um endereço de contrato ou um hash de arquivo IPFS) de um modelo especificado
              • logDataSources(templateName) imprime todas as fontes de dados do modelo especificado ao console, para propósitos de debug
              • readFile(path) lê um arquivo JSON que representa um arquivo IPFS e retorna o conteúdo como Bytes

              Teste de modelos ethereum/contract

              1test('ethereum/contract dataSource creation example', () => {2  // Impor que não há dataSources criadas de modelo GraphTokenLockWallet3  assert.dataSourceCount('GraphTokenLockWallet', 0)45  // Criar uma nova datasource GraphTokenLockWallet com o endereço 0xA16081F360e3847006dB660bae1c6d1b2e17eC2A6  GraphTokenLockWallet.create(Address.fromString('0xA16081F360e3847006dB660bae1c6d1b2e17eC2A'))78  // Assegurar que foi criada a dataSource9  assert.dataSourceCount('GraphTokenLockWallet', 1)1011  // Adicionar uma segunda dataSource com contexto12  let context = new DataSourceContext()13  context.set('contextVal', Value.fromI32(325))1415  GraphTokenLockWallet.createWithContext(Address.fromString('0xA16081F360e3847006dB660bae1c6d1b2e17eC2B'), context)1617  // Assertar que agora há 2 dataSources18  assert.dataSourceCount('GraphTokenLockWallet', 2)1920  // Impor que foi criada uma dataSource com o endereço "0xA16081F360e3847006dB660bae1c6d1b2e17eC2B"21  // Lembrar que o tipo `Address` transforma para caixa baixa quando decodificado, então o endereço deve ser passado como caixa-baixa ao determinar se existe22  assert.dataSourceExists('GraphTokenLockWallet', '0xA16081F360e3847006dB660bae1c6d1b2e17eC2B'.toLowerCase())2324  logDataSources('GraphTokenLockWallet')25})
              Exemplo de resultado de logDataSource
              1🛠  {2  "0xa16081f360e3847006db660bae1c6d1b2e17ec2a": {3    "kind": "ethereum/contract",4    "name": "GraphTokenLockWallet",5    "address": "0xa16081f360e3847006db660bae1c6d1b2e17ec2a",6    "context": null7  },8  "0xa16081f360e3847006db660bae1c6d1b2e17ec2b": {9    "kind": "ethereum/contract",10    "name": "GraphTokenLockWallet",11    "address": "0xa16081f360e3847006db660bae1c6d1b2e17ec2b",12    "context": {13      "contextVal": {14        "type": "Int",15        "data": 32516      }17    }18  }19}

              Teste de modelos file/ipfs

              Assim como as fontes dinâmicas de dados de contrato, os utilizadores podem testar fontes de dados de arquivos e os seus handlers

              Exemplo de subgraph.yaml
              1...2templates:3 - kind: file/ipfs4    name: GraphTokenLockMetadata5    network: mainnet6    mapping:7      kind: ethereum/events8      apiVersion: 0.0.99      language: wasm/assemblyscript10      file: ./src/token-lock-wallet.ts11      handler: handleMetadata12      entities:13        - TokenLockMetadata14      abis:15        - name: GraphTokenLockWallet16          file: ./abis/GraphTokenLockWallet.json
              Exemplo de schema.graphql
              1"""2Token Lock Wallets que têm GRT trancado3"""4type TokenLockMetadata @entity {5  "Endereço da token lock wallet"6  id: ID!7  "Começo da agenda de lançamento"8  startTime: BigInt!9  "Final da agenda de lançamento"10  endTime: BigInt!11  "Número de períodos entre o início e o fim"12  periods: BigInt!13  "Hora quando os lançamentos começam"14  releaseStartTime: BigInt!15}
              Exemplo de metadata.json
              1{2  "startTime": 1,3  "endTime": 1,4  "periods": 1,5  "releaseStartTime": 16}
              Exemplo de handler
              1export function handleMetadata(content: Bytes): void {2  // dataSource.stringParams() retorna CID de Fonte de Dados de Arquivo3  // stringParam() será simulado no teste de handler4  // para saber mais https://thegraph.com/docs/en/developing/creating-a-subgraph/#create-a-new-handler-to-process-files5  let tokenMetadata = new TokenLockMetadata(dataSource.stringParam())6  const value = json.fromBytes(content).toObject()78  if (value) {9    const startTime = value.get('startTime')10    const endTime = value.get('endTime')11    const periods = value.get('periods')12    const releaseStartTime = value.get('releaseStartTime')1314    if (startTime && endTime && periods && releaseStartTime) {15      tokenMetadata.startTime = startTime.toBigInt()16      tokenMetadata.endTime = endTime.toBigInt()17      tokenMetadata.periods = periods.toBigInt()18      tokenMetadata.releaseStartTime = releaseStartTime.toBigInt()19    }2021    tokenMetadata.save()22  }23}
              Exxemplo de teste
              1import { assert, test, dataSourceMock, readFile } from 'matchstick-as'2import { Address, BigInt, Bytes, DataSourceContext, ipfs, json, store, Value } from '@graphprotocol/graph-ts'34import { handleMetadata } from '../../src/token-lock-wallet'5import { TokenLockMetadata } from '../../generated/schema'6import { GraphTokenLockMetadata } from '../../generated/templates'78test('file/ipfs dataSource creation example', () => {9  // Gerar CID da dataSource do arquivo de local ipfsHash + ipfs10  // Por exemplo QmaXzZhcYnsisuue5WRdQDH6FDvqkLQX1NckLqBYeYYEfm/example.json11  const ipfshash = 'QmaXzZhcYnsisuue5WRdQDH6FDvqkLQX1NckLqBYeYYEfm'12  const CID = `${ipfshash}/example.json`1314  // Criar uma nova dataSource com o CID gerado15  GraphTokenLockMetadata.create(CID)1617  // Verificar se foi criada a dataSource18  assert.dataSourceCount('GraphTokenLockMetadata', 1)19  assert.dataSourceExists('GraphTokenLockMetadata', CID)20  logDataSources('GraphTokenLockMetadata')2122  // Agora temos que simular os metadados da dataSource, e especificamente dataSource.stringParam()23  // dataSource.stringParams usa o valor de dataSource.address(), então vamos simular o endereço24com dataSourceMock de matchstick-as25  // Primeiro, vamos reiniciar os valores e usar dataSourceMock.setAddress() para configurar o CID26  dataSourceMock.resetValues()27  dataSourceMock.setAddress(CID)2829  // Agora precisamos gerar os Bytes para passar para o handler da dataSource30  // Para este caso, apresentamos uma nova função readFile, que lê um json local e retorna o conteúdo como Bytes31  const content = readFile(`path/to/metadata.json`)32  handleMetadata(content)3334  // Agora vamos testar se foi criado um TokenLockMetadata35  const metadata = TokenLockMetadata.load(CID)3637  assert.bigIntEquals(metadata!.endTime, BigInt.fromI32(1))38  assert.bigIntEquals(metadata!.periods, BigInt.fromI32(1))39  assert.bigIntEquals(metadata!.releaseStartTime, BigInt.fromI32(1))40  assert.bigIntEquals(metadata!.startTime, BigInt.fromI32(1))41})

              Cobertura de Testes

              Using Matchstick, Subgraph developers are able to run a script that will calculate the test coverage of the written unit tests.

              A ferramenta de cobertura de testes pega os binários de teste wasm compilados e os converte a arquivos wat, que podem então ser facilmente vistoriados para ver se os handlers definidos em subgraph.yaml foram chamados ou não. Como a cobertura de código (e os testes em geral) está num estado primitivo no AssemblyScript e WebAssembly, o Matchstick não pode procurar por coberturas de branch. Em vez disto, supomos que, se um handler foi chamado, o evento/a função correspondente já foi simulado com êxito.

              Pré-requisitos

              Para executar a funcionalidade da cobertura de teste fornecida no Matchstick, prepare algumas coisas com antecedência:

              Exportar seus handlers

              Para que o Matchstick confira quais handlers serão executados, estes handlers devem ser exportados do arquivo de teste primeiro. No nosso exemplo, temos o seguinte handler a ser importado no nosso arquivo gravity.test.ts:

              1import { handleNewGravatar } from '../../src/gravity'

              Para que essa função seja visível (para ser incluída no arquivo wat por nome), também precisamos exportá-la assim:

              1export { handleNewGravatar }

              Uso

              Assim que tudo estiver pronto, para executar a ferramenta de cobertura de testes, basta:

              1graph test -- -c

              Um comando coverage personalizado também pode ser adicionado ao seu arquivo package.json, assim:

              1"scripts": {2    /.../3    "coverage": "graph test -- -c"4  },

              Isto executará a ferramenta de cobertura. Verás algo parecido com isto no terminal:

              1$ graph test -c2Skipping download/install step because binary already exists at /Users/petko/work/demo-subgraph/node_modules/binary-install-raw/bin/0.4.034___  ___      _       _         _   _      _5|  \/  |     | |     | |       | | (_)    | |6| .  . | __ _| |_ ___| |__  ___| |_ _  ___| | __7| |\/| |/ _` | __/ __| '_ \/ __| __| |/ __| |/ /8| |  | | (_| | || (__| | | \__ \ |_| | (__|   <9\_|  |_/\__,_|\__\___|_| |_|___/\__|_|\___|_|\_\1011Compiling...1213Running in coverage report mode.14 ️15Reading generated test modules... 🔎️1617Generating coverage report 📝1819Handlers for source 'Gravity':20Handler 'handleNewGravatar' is tested.21Handler 'handleUpdatedGravatar' is not tested.22Handler 'handleCreateGravatar' is tested.23Test coverage: 66.7% (2/3 handlers).2425Handlers for source 'GraphTokenLockWallet':26Handler 'handleTokensReleased' is not tested.27Handler 'handleTokensWithdrawn' is not tested.28Handler 'handleTokensRevoked' is not tested.29Handler 'handleManagerUpdated' is not tested.30Handler 'handleApproveTokenDestinations' is not tested.31Handler 'handleRevokeTokenDestinations' is not tested.32Test coverage: 0.0% (0/6 handlers).3334Global test coverage: 22.2% (2/9 handlers).

              Duração do teste na saída do log

              A saída do log inclui a duração do teste. Veja um exemplo:

              [Quinta, 31 Mar 2022 13:54:54 +0300] Programa executado em: 42.270ms.

              Erros comuns do compilador

              Critical: Could not create WasmInstance from valid module with context: unknown import: wasi_snapshot_preview1::fd_write has not been defined

              Isso significa que você usou console.log no seu código, que não é apoiado pelo AssemblyScript. Por favor, considere usar a API de registo

              ERROR TS2554: Expected ? arguments, but got ?.

              return new ethereum.Block(defaultAddressBytes, defaultAddressBytes, defaultAddressBytes, defaultAddress, defaultAddressBytes, defaultAddressBytes, defaultAddressBytes, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt, defaultBigInt);

              in ~lib/matchstick-as/assembly/defaults.ts(18,12) ERROR TS2554: Expected ? arguments, but got ?.

              return new ethereum.Transaction(defaultAddressBytes, defaultBigInt, defaultAddress, defaultAddress, defaultBigInt, defaultBigInt, defaultBigInt, defaultAddressBytes, defaultBigInt);

              in ~lib/matchstick-as/assembly/defaults.ts(24,12)

              A diferença nos argumentos é causada pela diferença no graph-ts e no matchstick-as. Problemas como este são melhor resolvidos ao atualizar tudo para a versão mais recente.

              Outros Recursos

              For any additional support, check out this demo Subgraph repo using Matchstick⁠.

              Feedback

              Caso tenha qualquer pergunta, opinião, pedidos de recursos, ou só quer entrar em contacto, venha para o Discord do The Graph — lá, temos um canal dedicado ao Matchstick, chamado 🔥| unit-testing.

              ⁠Editar no GitHub⁠

              ChangelogComo Implantar com o Subgraph Studio
              Nesta página
              • Vantagens de Usar o Matchstick
              • Como Começar
              • Como Instalar Dependências
              • Como Instalar o PostgreSQL
              • Usando o WSL (Subsistema do Windows para o Linux)
              • Usando o Matchstick
              • Opções de CLI
              • Docker
              • Configuração
              • Demo Subgraph
              • Tutoriais de vídeo
              • Estrutura de testes
              • describe()
              • test()
              • beforeAll()
              • afterAll()
              • beforeEach()
              • afterEach()
              • Asserts
              • Como Escrever um Teste de Unidade
              • Cenários de teste comuns
              • Como hidratar o armazenamento com um certo estado
              • Como chamar uma função de mapeamento com um evento
              • Como chamar todos os mapeamentos com fixações de eventos
              • Como simular chamadas de contratos
              • Como simular arquivos IPFS (do matchstick 0.4.1)
              • Como afirmar o estado do armazenamento
              • Como interagir com metadados de Eventos
              • Como afirmar a igualdade das variáveis
              • Como afirmar que uma Entidade não está no armazenamento
              • Impressão do armazenamento completo, ou de entidades individuais dele (para debugging)
              • Falhas esperadas
              • Logging
              • Como testar campos derivados
              • Teste de loadInBlock
              • Como testar fontes de dados dinâmicas
              • Teste de criação de fontes de dados dinâmicas
              • Cobertura de Testes
              • Pré-requisitos
              • Uso
              • Duração do teste na saída do log
              • Erros comuns do compilador
              • Outros Recursos
              • Feedback
              The GraphStatusRede de TestesAtivos de MarcaFórumSegurançaPolítica de PrivacidadeAcordo de Serviço