Найти тему

Тесты для встречного контракта

📚Чтение Заметок

Как я уже упоминал ранее, написание тестов будет очень солидной частью вашего времени на программирование контрактов FunC. Давайте подведем итоги наших тестов, созданных на предыдущем уроке:

Стоит отметить, что если мы запустим тест пряжи сейчас, он не сработает, потому что наш код значительно изменился. Что нам нужно сделать, чтобы исправить это, так это:

  1. Нам нужно предоставить надлежащие данные о начальном состоянии, поэтому в нашем хранилище c4 есть некоторые предварительно заполненные данные.
  2. Мы собираемся предоставить 0 в качестве значения счетчика и zeroAddress в качестве адреса отправителя с наибольшим количеством отправленных (в соответствии с новой логикой нашего контракта).

    Нам нужно передать конкретную команду операции внутри тела сообщения, которое мы отправляем в контракт.

Давайте разберемся с исходными данными. Как вы помните, мы используем метод createFromConfig для инициализации нашего контракта, и мы устанавливаем начальные данные состояния нашего контракта как простую пустую ячейку следующим образом:

static createFromConfig(config: any, code: Cell, workchain = 0) {
const data = beginCell().endCell();
const init = { code, data };
const address = contractAddress(workchain, init);
return new MainContract(address, init);
}

Затем createFromConfig вызывается в нашем main.spec.ts:

const myContract = blockchain.openContract(
await MainContract.createFromConfig({}, codeCell)
);

До сих пор мы передавали пустой объект в качестве конфигурации, но давайте теперь разрешим передачу значений, которые нам на самом деле понадобятся для инициализации соответствующих данных нашего контракта.

Давайте определим, как должна выглядеть наша конфигурация. Сразу после импорта в наших обертках
/MainContract.ts мы определим новый тип под названием MainContractConfig.

// ... library imports

export type MainContractConfig = {
number: number;
address: Address;
};

Еще одна классная функция помощи, которую мы собираемся реализовать в том же файле обертки, будет mainContractConfigToCell. Он получит объект типа MainContractConfig, правильно упакует эти параметры в ячейку и вернет ее. Нам это нужно, потому что, как вы помните, хранилище c4 - это ячейка памяти:

// ... library imports
// ... MainContractConfig type
export function mainContractConfigToCell(config: MainContractConfig): Cell {
return beginCell().storeUint(config.number, 32).storeAddress(config.address).endCell();
}

Теперь давайте обновим createFromConfig в том же файле, но внутри класса MainContract. Теперь он должен использовать функцию mainContractConfigToCell для формирования ячейки данных начального состояния:

-2

Теперь, когда наш метод createFromConfig готов, давайте обновим, как мы используем его в нашем файле tests/main.spec.ts:

-3

Обратите внимание, как мы создали кошелек initAddress (казначейство) из начальной "initAddress", чтобы передать его адрес в метод createFromConfig нашего MainContract.

На данный момент мы успешно инициализируем наш контракт! Поздравляю :)

Поскольку теперь мы также собираемся отправить определенные данные внутри тела сообщения, давайте обновим метод sendInternalMessage в наших обертках
/MainContract.ts.

Мы собираемся переименовать его в sendIncrement, и теперь он примет еще одно значение
- increment_by. Это будет номер для укращения стоимости хранения текущего контракта.

Мы также имеем в виду, что это тот же орган, который разборирует наш контракт, чтобы получить код операции. Итак, давайте не забудем сначала сохранить 32-битное целое число (1 для приращения, как вы можете видеть в коде нашего контракта), а затем - 32-битное целое число для приращения значения:

-4

Есть еще один метод, который нам нужно обновить в нашей обертке - getData. Как вы помните, мы переименовали метод getter, а также теперь он возвращает два значения. Давайте скорректируем наш метод обертки:

async getData(provider: ContractProvider) {
const { stack } = await provider.get("get_contract_storage_data", []);
return {
number: stack.readNumber(),
recent_sender: stack.readAddress(),
};
}

Обратите внимание, как мы читаем результирующий стек метода геттера. Мы читаем Number(), чтобы прочитать целое число текущего значения.

Теперь мы все готовы вернуться к нашим тестам
/main.spec.ts и продолжить прохождение нашего теста. Вот обновленный код нашего теста:

-5

Что мы здесь обновили?

  1. Теперь мы передаем число - 1 - в метод sendIncrement, поэтому наше результирующее значение должно быть увращено на 1.
  2. Мы установили ожидания для значений recent_sender и number.

Теперь мы можем запустить наш тест с помощью команды yarn test. Если вы все сделали правильно - в терминале вы увидите следующее:

PASS tests/main.spec.ts
main.fc contract tests
✓ should successfully increase counter in contract and get the proper most recent sender address (452 ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.339 s, estimated 5 s

Вуаля, наш встречный контракт теперь должным образом протестирован. С нетерпением жду дополнительной логики на следующих уроках!

LikBez Crypto 2.0