【问题标题】:Testing Smart contract requires in Truffle: transaction reverted if function isnt void在 Truffle 中测试智能合约需要:如果功能不无效,则交易恢复
【发布时间】:2018-06-11 21:59:09
【问题描述】:

我正在尝试根据本文仅使用可靠性来测试智能合约的要求:

http://truffleframework.com/tutorials/testing-for-throws-in-solidity-tests

这是合约,throw代理合约和测试:

/* Testing with solidity tests. */

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/MyContract.sol";

contract TestMyContract {

function testInitialStoredValue() {
    MyContract mycontract = new MyContract();

    uint expected = 24;

    Assert.equal(mycontract.mynumber(), expected, "First number set should be 24.");
}

function testTheThrow() {
    MyContract mycontract = new MyContract(); 

    ThrowProxy throwproxy = new ThrowProxy(address(mycontract)); 
    uint num = 7;
    MyContract(address(throwproxy)).storeNum(num);

    bool r = throwproxy.execute.gas(200000)(); 

    Assert.isFalse(r, "Should be false because is should throw!");

}

function testNoThrow() {
    MyContract mycontract = new MyContract(); 

    ThrowProxy throwproxy = new ThrowProxy(address(mycontract)); 

    MyContract(address(throwproxy)).storeNum(22);

    bool r = throwproxy.execute.gas(200000)(); 

    Assert.isTrue(r, "Should be true because is should throw!");

}

}

// Proxy contract for testing throws
contract ThrowProxy {
  address public target;
  bytes data;

  function ThrowProxy(address _target) {
    target = _target;
  }

  //prime the data using the fallback function.
  function() {
    data = msg.data;
  }

  function execute() returns (bool) {
    return target.call(data);
  }
}

如果我运行测试,我会收到此错误:

如果我将 storeNum 函数更改为 void

 function storeNum(uint mynum)
        public
        returns (bool)
    {
     require(mynum > 10);
     mynumber = mynum; 
     return true;    
    }

 function storeNum(uint mynum)
        public
    {
     require(mynum > 10);
     mynumber = mynum; 
     return true;    
    }

测试有效..

有什么想法吗?

我正在使用 Truffle v4.1.11

【问题讨论】:

    标签: testing ethereum solidity truffle


    【解决方案1】:

    让我们看看你的代码:

    function storeNum(uint mynum)
            public
            returns (bool success)
        {
         require(mynum > 10);
         mynumber = mynum; 
         return true;    
        }
    

    通过定义returns (bool success),您对solidity 编译器说两件事:

    • 有一个变量名为success,类型为bool(变量定义)
    • 该变量成功将由函数返回(返回定义)

    但您的变量毕竟没有返回(您的函数以 return true 结尾,这就是您在测试中收到 InvalidResponse 错误的原因。

    对于您的代码,最有效的代码是:

    function storeNum(uint mynum)
            public
            returns (bool)    // you should define at least the type
        {
         require(mynum > 10);
         mynumber = mynum; 
         return true;    
        }
    

    作为练习,使用变量success的版本:

    function storeNum(uint mynum)
            public
            returns (bool success)
        {
         require(mynum > 10);
         mynumber = mynum; 
         success = true;    // don't need to use return
        }
    

    希望对你有帮助。

    【讨论】:

    • 嗨,我明白了,但这似乎不是问题的原因,我遇到了同样的错误。
    • 我觉得这个链接对你有很大帮助:medium.com/@kscarbrough1/…
    • 其实这就是我举的例子
    【解决方案2】:

    好吧,我已经向 Truffle github 提交了一个问题,它仍然处于打开状态,可能这与最近的 Solidity 更改有关:

    https://github.com/trufflesuite/truffle/issues/1001

    目前的解决方法是将函数包装成 void 函数并测试执行是否成功:

    /*
        Contract wrapper that inherits from MyContract. This contract wraps the calls of non void functions when
        testing for exceptions.
    
        Why not invoke directly the function?: https://github.com/trufflesuite/truffle/issues/1001
    */
    
    contract MyExposedContract is MyContract() {
    
    
        function callStoreNum(uint256 num)  public {
            storeNum(num);
        }
    
    }
    

    然后在您的测试中使用该包装器:

    function testTheThrow() {
        MyExposedContract mycontract = new MyExposedContract (); 
    
        ThrowProxy throwproxy = new ThrowProxy(address(mycontract)); 
        uint num = 7;
        MyExposedContract (address(throwproxy)).callStoreNum(num);
    
        bool r = throwproxy.execute.gas(200000)(); 
    
        Assert.isFalse(r, "Should be false because it should throw!");
    
    }
    

    【讨论】:

    • 我正在尝试将包装类与 Solidity v0.5 一起使用的解决方法,但它不起作用。此外,在包装器中您定义了callStoreNum,但在测试中您仍然调用storeNum
    • 尚未尝试使用solidity 0.5。谢谢,我已经修复了答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 2021-10-29
    • 2020-05-26
    • 1970-01-01
    相关资源
    最近更新 更多