인프런 커뮤니티 질문&답변

이경수님의 프로필 이미지

작성한 질문수

모두를 위한 모두의 EVM 블록체인 BApp 개발 - 입문

npx hardhat test ./test/Greeter.test 실행시 에러가 납니다.

해결된 질문

작성

·

143

1

npx hardhat test ./test/Greeter.test 실행시 에러가 납니다.

import { expect } from 'chai';
import { ethers, waffle } from 'hardhat';
import GreeterArtifact from '../artifacts/contracts/Greeter.sol/Greeter.json';
import { Greeter } from '../typechain';
// import { BigNumber } from 'ethers';
// import '@nomiclabs/hardhat-waffle';

//* Greeter.sol과 비교하면서 보자!!
describe('Greeter', () => {
  let greeter: Greeter;
  const initMsg = 'hello blockchain!!!';

  //* hardHat에서 만들어진 10개 계정부터 앞에 5개 가져옴.
  const [admin, other0, other1, other2, receiver] =
    waffle.provider.getWallets();

  before(async () => {});

  beforeEach(async () => {
    //admin계정이 Greeter 배포
    greeter = (await waffle.deployContract(admin, GreeterArtifact, [
      initMsg,
    ])) as Greeter; //* Greeter로 형변환 해서 넣어주라는 뜻
  });

  it('constructor', async () => {
    const greetMsg = await greeter.getGreet();
    expect(greetMsg).to.be.equal(initMsg);
  });

  it('setGreeting', async () => {
    const secondMsg = 'second greeting msg';

    await greeter.setGreeting(secondMsg);
    //* 이렇게 unit 테스트인 경우에만 hardhat이 transaction.wait()을 사용하지 않아도 결과를 기다림.
    const recvMsg = await greeter.getGreet();
    expect(recvMsg).to.be.equal(secondMsg);
  });

  it('setGreeting with event', async () => {
    const secondMsg = 'second greeting msg';

    /*
     * setGreeting -> non-view함수 -> 채굴할 때까지 기다려야함.
     * transaction.wait()을 호출하여 채굴이 끝날 때까지 기다린다.
     */
    const transaction = await greeter.setGreeting(secondMsg);
    //* transaction을통해 채굴이 끝난 후 영수증을 가져옴.
    const receipt = await transaction.wait();

    //영수증 안의 이벤트에서 SetGreeting이라는 event만 가져온다.
    const event = receipt.events?.filter(x => {
      return x.event == 'SetGreeting';
    })[0];

    //* contract배포자가 admin이라서 자동으로 admin으로 설정됨.
    //* ? : undefined가 될수도 있다. ~> 실제로는 예외처리 필요
    expect(event?.args?.sender).to.be.equal(admin.address);
    expect(event?.args?.oldGreeting).to.be.equal(initMsg);
    expect(event?.args?.newGreeting).to.be.equal(secondMsg);

    const thirdMsg = 'third greeting msg';
    await expect(greeter.setGreeting(thirdMsg))
      .to.emit(greeter, 'SetGreeting')
      .withArgs(admin.address, secondMsg, thirdMsg);
  });

  it('getGreetingHistory', async () => {
    const secondMsg = 'second greeting msg';

    const transaction = await greeter.setGreeting(secondMsg);
    const receipt = await transaction.wait();

    const thirdMsg = 'third greeting msg';
    await expect(greeter.setGreeting(thirdMsg))
      .to.emit(greeter, 'SetGreeting')
      .withArgs(admin.address, secondMsg, thirdMsg);

    const count = await greeter.getGreetingHistoryCount();
    expect(count).to.be.equal(3);

    const historyAll = await greeter.getGreetingHistoryAll();
    expect(historyAll.length).to.be.equal(3);
    expect(historyAll[0]).to.be.equal('');
    expect(historyAll[1]).to.be.equal(initMsg);
    expect(historyAll[2]).to.be.equal(secondMsg);

    const secondHistory = await greeter.getGreetingHistoryOne(1);
    expect(secondHistory).to.be.equal(initMsg);
    //* 없는 인덱스 예상 했을 때 revert메시지 나오는지
    await expect(greeter.getGreetingHistoryOne(3)).to.reverted;
  });

  it('setGreetingPayable', async () => {
    const secondMsg = 'second greeting msg';

    await expect(greeter.setGreetingPayable(secondMsg)).to.reverted;
    //* revert문 예상
    await expect(greeter.setGreetingPayable(secondMsg)).to.revertedWith(
      'msg.value is not 0.1 ether',
    );

    await expect(
      greeter.setGreetingPayable(secondMsg, {
        value: ethers.utils.parseUnits('0.09', 'ether'),
      }),
    ).to.revertedWith('msg.value is not 0.1 ether');

    await expect(
      greeter.setGreetingPayable(secondMsg, {
        value: ethers.utils.parseUnits('0.11', 'ether'),
      }),
    ).to.revertedWith('msg.value is not 0.1 ether');

    await greeter.setGreetingPayable(secondMsg, {
      //* value를 wei로 바꿔줌.(ehter단위)
      value: ethers.utils.parseUnits('0.1', 'ether'),
      //~> 이렇게도 가능
      // value: BigNumber.from(10).pow(17),
    });

    const recvMsg = await greeter.getGreet();
    expect(recvMsg).to.be.equal(secondMsg);
  });

  it('withdraw', async () => {
    const secondMsg = 'second greeting msg';

    //* setGreetingPayable을 실행하기 전에 Ether가 얼마나 들었는지 확인하기 위함.
    const oldContractEther = await waffle.provider.getBalance(greeter.address);

    expect(oldContractEther).to.be.equal(ethers.utils.parseUnits('0', 'ether'));

    //*admin 호출
    // await greeter.connect(admin).setGreetingPayable(secondMsg, {
    // await greeter.setGreetingPayable(){}
    //*admin이 아닌 다른 계정이 호출
    await greeter.connect(other0).setGreetingPayable(secondMsg, {
      value: ethers.utils.parseUnits('0.1', 'ether'),
    });
    await greeter.connect(other0).setGreetingPayable(secondMsg, {
      value: ethers.utils.parseUnits('0.1', 'ether'),
    });

    await greeter.connect(other1).setGreetingPayable(secondMsg, {
      value: ethers.utils.parseUnits('0.1', 'ether'),
    });
    await greeter.connect(other2).setGreetingPayable(secondMsg, {
      value: ethers.utils.parseUnits('0.1', 'ether'),
    });

    //위에서 0.1씩 4번 호출 -> 0.4 ether
    const newContractEther = await waffle.provider.getBalance(greeter.address);
    expect(newContractEther).to.be.equal(
      ethers.utils.parseUnits('0.4', 'ether'),
    );

    const other0Balance = await greeter.balances(other0.address);
    const other1Balance = await greeter.balances(other1.address);
    const other2Balance = await greeter.balances(other2.address);

    expect(other0Balance).to.be.equal(ethers.utils.parseUnits('0.2', 'ether'));
    expect(other1Balance).to.be.equal(ethers.utils.parseUnits('0.1', 'ether'));
    expect(other2Balance).to.be.equal(ethers.utils.parseUnits('0.1', 'ether'));

    //* 얼마나 ether를 들고 있었는지 확인
    const oldReceiverEther = await waffle.provider.getBalance(receiver.address);
    console.log('oldReceiverEther', oldReceiverEther);
    await expect(
      greeter.connect(other0).withdraw(receiver.address),
    ).to.revertedWith('only owner');

    //*connect 생략 -> admin
    await greeter.withdraw(receiver.address);
    const newReceiverEther = await waffle.provider.getBalance(receiver.address);

    expect(newReceiverEther.sub(oldReceiverEther)).to.be.equal(
      ethers.utils.parseUnits('0.4', 'ether'),
    );

    const lastContractEther = await waffle.provider.getBalance(greeter.address);
    expect(lastContractEther).to.be.equal(
      ethers.utils.parseUnits('0', 'ether'),
    );
  });
});

 

import { HardhatUserConfig } from 'hardhat/types';
import 'hardhat-typechain';
import '@nomiclabs/hardhat-waffle';
// import 'dotenv/config';
const config: HardhatUserConfig = {
  solidity: {
    compilers: [
      {
        version: '0.8.17',
        settings: {
          optimizer: {
            enabled: true,
            runs: 200,
          },
        },
      },
    ],
  },
  defaultNetwork: 'hardhat',
  networks: {
    hardhat: {
      accounts: {
        count: 10,
      },
    },
  },
  mocha: {
    timeout: 400000,
  },
};

export default config;

아래와 같은 문구가 나타납니다.
Creating Typechain artifacts in directory typechain for target ethers-v5

Successfully generated Typechain artifacts!

Greeter

1) "before each" hook for "constructor"

0 passing (99ms)

1 failing

1) Greeter

"before each" hook for "constructor":

Error: Cannot find module 'ethereum-waffle/dist/cjs/src/deployContract'

Require stack:

- /Users/nareun130/study/nft/basic/node_modules/@nomiclabs/hardhat-waffle/dist/src/deploy.js

- /Users/nareun130/study/nft/basic/node_modules/@nomiclabs/hardhat-waffle/dist/src/index.js

- /Users/nareun130/study/nft/basic/hardhat.config.ts

- /Users/nareun130/study/nft/basic/node_modules/hardhat/internal/core/config/config-loading.js

- /Users/nareun130/study/nft/basic/node_modules/hardhat/internal/cli/cli.js

- /Users/nareun130/study/nft/basic/node_modules/hardhat/internal/cli/bootstrap.js

at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1140:15)

at Function.Module._resolveFilename.sharedData.moduleResolveFilenameHook.installedValue [as resolveFilename] (nodemodules/@cspotcode/source-map-support/source-map-support.js:811:30)

at Function.Module._load (node:internal/modules/cjs/loader:981:27)

at Module.require (node:internal/modules/cjs/loader:1231:19)

at require (node:internal/modules/helpers:177:18)

at hardhatDeployContract (node_modules/@nomiclabs/hardhat-waffle/src/deploy.ts:26:7)

at Context.<anonymous> (test/Greeter.test.ts:21:29)


deploy.ts의 26라인을 가봤는데 이렇게 나오는데 node_modules의 경로를 찾아가보니 ethereum-waffle/cjs폴더 안에 src폴더가 없이 바로 아래 deployContract가 있어서 그런건지 해결방법을 잘 모르겠습니다.

도와주세요 ㅠ

 

답변 1

0

모영철님의 프로필 이미지
모영철
지식공유자

최신 라이브러리 버젼과 코드 호환이 안 되는걸 확인했습니다.

강의 제작당시 버전으로 fix해 두었으니

  • node_modules 폴더와 package-lock.json 파일을 삭제

  • 강의 코드 최신버전으로 git pull

  • npx hardhat test ./test/Greeter.test 실행

이 방법으로 실행되는걸 확인했습니다.

이경수님의 프로필 이미지
이경수
질문자

감사합니다! 정상적으로 실행되는 것을 확인했습니다.