简体   繁体   English

火柴棍:断言错误:预期字段等于“”但为“”

[英]Matchstick: Assertion error: expected field equal '' but was ''

During testing my Graph Project I receive the following error:在测试我的 Graph 项目期间,我收到以下错误:

nft-lottery
  Player entity
        𝖷 (assert.fieldEquals) Expected field 'lotteries' to equal '[0x1]', but was '[]' instead.
        🛠  Mapping aborted at ~lib/matchstick-as/assembly/assert.ts, line 13, column 7, with message: Assertion Error
wasm backtrace:
    0: 0x387c - <unknown>!~lib/matchstick-as/assembly/assert/assert.fieldEquals
    1: 0x38fa - <unknown>!start:tests/nft-lottery.test~anonymous|0~anonymous|3

If I log the results after calling handleNftLotteryEnter() function I get (ie, the lottery.id has not been stored even though it should have as it is derivedFrom the NftLottery - see below):如果我在调用handleNftLotteryEnter() function 后记录结果(即,lottery.id 没有被存储,即使它应该有,因为它是从 NftLottery 派生的 - 见下文):

"Player": {
    "0xdb...a7bf": {
      "lotteries": {
        "type": "List",
        "data": []
      }
    }
  },
...

If I try to mock firing three subsequent events, the first two players has got values stored but the last one has not, ie:如果我尝试模拟触发三个后续事件,前两个玩家已经存储了值,但最后一个没有,即:

"Player": {
    "0x5a...3ca1": {
      "lotteries": {
        "type": "List",
        "data": [
          {
            "type": "String",
            "data": "0x1"
          }
        ]
      }
    },
    "0xd1...6575": {
      "lotteries": {
        "type": "List",
        "data": []
      }
    },
    "0xdb...a7bf": {
      "lotteries": {
        "type": "List",
        "data": [
          {
            "type": "String",
            "data": "0x1"
          }
        ]
      }
    }
  },

What could be the reason thereof?可能是什么原因? Thank you in advance!先感谢您!

Test file测试文件

import {
  assert,
  describe,
  test,
  clearStore,
  beforeAll,
  afterAll,
  logStore,
} from "matchstick-as/assembly/index"
import { BigInt, Address } from "@graphprotocol/graph-ts"
import { handleNftLotteryEnter } from "../src/nft-lottery"
import { createNftLotteryEnterEvent } from "./nft-lottery-utils"

describe("Enter the NFT Lottery 1x", () => {  
  beforeAll(() => {  
    let lotteryCounter = BigInt.fromI32(1)
    let player_one = Address.fromString("0xDB...a7bf")
    let entranceFee = BigInt.fromI32(1)
    
    let newNftLotteryEnterEvent = createNftLotteryEnterEvent(
      lotteryCounter,
      player_one,
      entranceFee
    )
    handleNftLotteryEnter(newNftLotteryEnterEvent)
    logStore()
  })

  afterAll(() => {
    clearStore()
  })

  test("Player entity", () => {
    assert.fieldEquals("Player", "0xdb...a7bf", "lotteries", "[0x1]")
  })
})

describe("Enter the NFT Lottery 3x", () => {
  beforeAll(() => {
    let lotteryCounter = BigInt.fromI32(1)
    let entranceFee = BigInt.fromI32(1)

    let player_one = Address.fromString("0xDB...a7bf")
    let player_two = Address.fromString("0x5a...3cA1")
    let player_three = Address.fromString("0xd1...6575")

    // the first event
    let oneNftLotteryEnterEvent = createNftLotteryEnterEvent(
      lotteryCounter,
      player_one,
      entranceFee
    )
    handleNftLotteryEnter(oneNftLotteryEnterEvent)
    // the second event
    let twoNftLotteryEnterEvent = createNftLotteryEnterEvent(
      lotteryCounter,
      player_two,
      entranceFee
    )
    // the third event 
    handleNftLotteryEnter(twoNftLotteryEnterEvent)
    let threeNftLotteryEnterEvent = createNftLotteryEnterEvent(
      lotteryCounter,
      player_three,
      entranceFee
    )
    handleNftLotteryEnter(threeNftLotteryEnterEvent)
    logStore()
  })

  afterAll(() => {
    clearStore()
  })

  test("Counts", () => {
    assert.entityCount("NftLottery", 1)
    assert.entityCount("Player", 3)
  })
  test("Player Entity 3x", () => {
    assert.fieldEquals("Player", "0xdb...a7bf", "lotteries", "[0x1]")
  })
})

Schema.graphql Schema.graphql

type NftLottery @entity {
  id: ID!
  openAtTimestamp: BigInt!
  closeAtTimestamp: BigInt!
  prize: BigInt!
  players: [Player!]!
  winners: [Player!]
  requestId: BigInt
  updatedAtTimestamp: BigInt
}

type Player @entity {
  id: ID! # address
  lotteries: [NftLottery!]! @derivedFrom(field: "players")
}

# events
type NftLotteryEnter @entity {
  id: ID! # Set lotteryCounter + playerAddress
  lotteryCounter: BigInt!
  player: Bytes!
  numberOfEntrances: [BigInt!]!
  updatedAtTimestamp: BigInt
}

Handlers处理程序

import { BigInt, Address } from "@graphprotocol/graph-ts"
import {
  NftLotteryEnter as NftLotteryEnterEvent
} from "../generated/NftLottery/NftLottery"
import { NftLottery, Player, NftLotteryEnter } from "../generated/schema"

export function handleNftLotteryEnter(event: NftLotteryEnterEvent): void {
  /* Event params */
  const playerId = event.params.player.toHexString()
  const lotteryId = event.params.lotteryCounter.toHexString()
  const entranceFee = event.params.entranceFee.toString()
  const lotteryPlayerId = lotteryId + playerId
  /* NftLottery: if a lottery does not exist, create it */ 
  let nftLottery = NftLottery.load(lotteryId)
  if (!nftLottery) {
    nftLottery = new NftLottery(lotteryId)
    nftLottery.openAtTimestamp = event.block.timestamp
    nftLottery.closeAtTimestamp = BigInt.fromString("000000000000")
    nftLottery.requestId = BigInt.fromString("0")
    nftLottery.prize = BigInt.fromString("0")
    nftLottery.players = new Array<string>()
    nftLottery.winners = new Array<string>()
  }
  // update lottery data
  let currentPrize = nftLottery.prize
  nftLottery.prize = currentPrize.plus(BigInt.fromString(entranceFee))
  // update players
  let arrPlayers = nftLottery.players
  arrPlayers.push(playerId)
  nftLottery.players = arrPlayers

  nftLottery.updatedAtTimestamp = event.block.timestamp
  nftLottery.save()

  /* Player: if a player does not exist, create them */
  let player = Player.load(playerId)
  if (!player) {
    player = new Player(playerId)
    player.save()
  }

  /* NftLotteryEnter */
  let nftLotteryEnter = NftLotteryEnter.load((lotteryPlayerId))
  if (!nftLotteryEnter) {
    nftLotteryEnter = new NftLotteryEnter(lotteryPlayerId)
    nftLotteryEnter.lotteryCounter = BigInt.fromString(event.params.lotteryCounter.toString())
    nftLotteryEnter.player = Address.fromHexString(playerId)
    nftLotteryEnter.numberOfEntrances = BigInt.fromString("0")
  }
  // update entrances
  const entrances = nftLotteryEnter.numberOfEntrances
  nftLotteryEnter.numberOfEntrances = entrances.plus(BigInt.fromString("1"))
  nftLotteryEnter.save()
}

There might be a bug in Matchstick testing tool: Matchstick 测试工具中可能存在错误:

  • As PlayerEntity derives lotteries from NftLottery , the NftLottery should be saved AT THE END of all operations related to both entities.由于PlayerEntityNftLottery派生彩票,因此NftLottery应保存与两个实体相关的所有操作的末尾。
  • Otherwise Player.lotteries does not get updated immediately and it stays empty, thus test fails.否则Player.lotteries不会立即更新并保持为空,因此测试失败。
  ...
  // update when updated
  nftLottery.updatedAtTimestamp = event.block.timestamp

  /* Player: if a player does not exist, create them */
  let player = Player.load(playerId)
  if (!player) {
    player = new Player(playerId)
    player.save()
  }
  nftLottery.save()
  ...

Credit goes to Maks#3349 at unit testing of Graph discord.归功于 Maks#3349 在图 discord 的单元测试中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM