18

How can we unit test contract private functions using the Truffle framework?

Since Solidity doesn't have package access or reflection language features, standard private testing approaches don't work.

Creating a test contract which inherits from the contract we're testing seems to be the only approach that works. However these tests would run on the blockchain.

Is there a way to unit test private functions from Javascript?

Daniel Que
  • 783
  • 7
  • 21

4 Answers4

25

If they are internal functions you can inherit them and test them, if they are private functions, I believe the only way to unit test them is to make them public/internal, test them and then change them back to private once the tests are passing.

Another way to go about it would be to refactor your code so that the private functions are part of a library that you import into the contract. That way the functions are public in the library but not exposed in the actual contract.

Daniel Que
  • 783
  • 7
  • 21
Nanolucas
  • 769
  • 5
  • 16
  • 10
    I'm not sure that refactor your code for the tests is a good idea.. For now I'm looking for better solutions. – leonprou Feb 06 '18 at 10:14
  • 2
    I never said it was a good solution, but from my understanding it's one of the only solutions – Nanolucas Feb 07 '18 at 01:07
  • Yeah I see, thanks for answering. Looking into it more thorough I see how complex the issue is. As I understand, to do this we need to manipulate the compiled contract in our test suite. – leonprou Feb 08 '18 at 06:23
2

For anyone using Foundry, the recommended advice for testing internal functions is to inherit and expose them as external ones.

This can be done directly in the .t.sol file, so you don't have to worry about adding extra files / contracts to your project. See below for the example from the Foundry Book.

// file: src/MyContract.sol
contract MyContract {
  function myInternalMethod() internal returns (uint) {
    return 42;
  }
}

// file: test/MyContract.t.sol import {MyContract} from "src/MyContract.sol";

contract MyContractHarness is MyContract { // Deploy this contract then call this method to test myInternalMethod. function exposed_myInternalMethod() external returns (uint) { return myInternalMethod(); } }

In Foundry, there isn't a good way of testing private functions yet. Besides renaming them as internal, the Foundry book also suggests copying and pasting them into your .t.sol file and running a script to ensure both functions implementations match.

NNNComplex
  • 23
  • 3
1

Assuming that unit testing can be done locally (Ganache or Local Hardhat) and you have access to the source code, you could create a duplicate of the smart contract. With this duplicate, use public functions that call the private methods to test for functionality.

0

You can inherit the contract to a TestContract that has public methods that just call the private/internal methods. This way you can test the correctness of the methods in the original contract without modifying their visibility.

  • You cannot inherit private methods, as mentionned in the accepted answer already. – samlaf Feb 21 '22 at 16:42
  • I guess you didn't read my answer. You inherit the original contract and ADD public methods that just call the private ones, not inherit them. – Miron Ophir Feb 23 '22 at 08:15
  • Private functions can only be called from inside the contract; inherited contracts can't call them. https://solidity-by-example.org/visibility/ – samlaf Feb 23 '22 at 16:58