Waffle icon indicating copy to clipboard operation
Waffle copied to clipboard

Not clear how to mock a contract method with no return

Open Remscar opened this issue 4 years ago • 5 comments

There is great documentation on using the mock contracts, but it doesn't seem like it's possible to mock out a contract method that doesn't have a return value.

Our use case is this:

Contract A calls Contract B internally. We mock out Contract B. The function being called emits an event but doesn't have a return value.

Since we are unable to mock out the function on Contract B (with .returns) it fails with Error: VM Exception while processing transaction: revert Mock on the method is not initialized

We mock it out, making it fail, but we cannot test it passing successfully.

Remscar avatar Apr 13 '21 20:04 Remscar

returns() should work in fact.

See my example for other issue repro https://github.com/EthWorks/Waffle/compare/master...wachulski:issue/477/mocking-calldata-example#diff-0384d1b80f7b6a2a5650f6c841b5849286719ea918694c2eb45cb71a87ae9e11R51

But yeah, it's not clear enough in docs. Adding a label

wachulski avatar Apr 14 '21 12:04 wachulski

@wachulski do you have an example ? Using the AmIRichAlready example, I simply added in the contructor of AmIRichAlready tokenContract.approve(0xeeeEEEeeeEEEeeeEEEeeeEEEeeeEEEeeeeEEEEEe, 10); and in a test file await mockERC20.mock.approve.returns(); before deploying + injecting mockERC20

resulted in an error : Error: types/values length mismatch (count={"types":1,"values":0}, value={"types":[{"name":null,"type":"bool","indexed":null,"components":null,"arrayLength":null,"arrayChildren":null,"baseType":"bool","_isParamType":true}],"values":[]}, code=INVALID_ARGUMENT, version=abi/5.3.1)

Seems to have to expected behavior if we change that to await mockERC20.mock.approve.reverts(); where the deployment fails as expected

Singtah avatar Jun 14 '21 16:06 Singtah

Duplicate of https://github.com/EthWorks/Waffle/issues/360.

PaulRBerg avatar Jun 29 '21 09:06 PaulRBerg

ya, the docs can be better about this. had to dig to find that "safeTransferFrom(address,address,uint256)" was a possible arg formock

await mockDeedRepository.mock["safeTransferFrom(address,address,uint256)"]
        .withArgs(this.auctionRepository.address, ownerAddr, deedId)
        .returns();

chang-ryan avatar Mar 03 '22 19:03 chang-ryan

I believe there is a problem with how this check works. I wanna test that my contract transfer fails when the recipient contract doesnt implement IERC721Receiver. I dont need to implement a full contract, just mock one, but my mock should NOT have the function it's trying to validate, because thats what my test is doing. But.... I can't test it, because instead of passing my test (tests that should fail) it throws this exception.... any ideas?

JuanuMusic avatar May 30 '22 10:05 JuanuMusic