प्रमुख मजकुराकडे जा

चाचणीसाठी Solidity स्मार्ट कॉन्ट्रॅक्ट्सना मॉक कसे करावे

Solidity
स्मार्ट कॉन्ट्रॅक्ट
चाचणी
मॉक करणे
मध्यम
Markus Waas
२ मे, २०२०
4 मिनिट वाचन

मॉक ऑब्जेक्ट्स (opens in a new tab) हे ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंगमधील एक सामान्य डिझाइन पॅटर्न आहे. जुन्या फ्रेंच शब्द 'mocquer' ज्याचा अर्थ 'गमतीचा विषय बनवणे' आहे, त्यापासून विकसित होऊन त्याचा अर्थ 'खऱ्या गोष्टीची नक्कल करणे' असा झाला, जे आपण प्रोग्रामिंगमध्ये प्रत्यक्षात करत आहोत. तुम्हाला हवे असल्यास कृपया तुमच्या स्मार्ट कॉन्ट्रॅक्ट्सची गंमत करा, परंतु जेव्हा शक्य असेल तेव्हा त्यांना मॉक करा. हे तुमचे जीवन सोपे करते.

मॉकसह कॉन्ट्रॅक्ट्सची युनिट-चाचणी

कॉन्ट्रॅक्ट मॉक करणे म्हणजे मूलतः त्या कॉन्ट्रॅक्टची दुसरी आवृत्ती तयार करणे जी मूळ आवृत्तीसारखीच वागते, परंतु अशा प्रकारे की डेव्हलपरद्वारे ती सहजपणे नियंत्रित केली जाऊ शकते. तुमच्याकडे अनेकदा गुंतागुंतीचे कॉन्ट्रॅक्ट्स असतात जिथे तुम्हाला फक्त कॉन्ट्रॅक्टच्या छोट्या भागांची युनिट-चाचणी करायची असते. समस्या ही आहे की, जर या छोट्या भागाची चाचणी करण्यासाठी एका विशिष्ट कॉन्ट्रॅक्ट स्थितीची आवश्यकता असेल ज्यात पोहोचणे कठीण आहे, तर काय?

तुम्ही प्रत्येक वेळी गुंतागुंतीचे चाचणी सेटअप लॉजिक लिहू शकता जे कॉन्ट्रॅक्टला आवश्यक स्थितीत आणेल किंवा तुम्ही मॉक लिहू शकता. इनहेरिटन्ससह कॉन्ट्रॅक्ट मॉक करणे सोपे आहे. फक्त एक दुसरा मॉक कॉन्ट्रॅक्ट तयार करा जो मूळ कॉन्ट्रॅक्टमधून इनहेरिट करतो. आता तुम्ही तुमच्या मॉकसाठी फंक्शन्स ओव्हरराइड करू शकता. चला एका उदाहरणासह पाहूया.

उदाहरण: प्रायव्हेट ERC20

आपण एका उदाहरणादाखल ERC-20 कॉन्ट्रॅक्टचा वापर करतो ज्यामध्ये सुरुवातीला एक खाजगी वेळ असतो. मालक खाजगी वापरकर्त्यांना व्यवस्थापित करू शकतो आणि सुरुवातीला फक्त त्यांनाच टोकन मिळवण्याची परवानगी असेल. एकदा ठराविक वेळ निघून गेल्यावर, प्रत्येकाला टोकन वापरण्याची परवानगी दिली जाईल. तुम्हाला उत्सुकता असल्यास, आम्ही नवीन OpenZeppelin contracts v3 मधून _beforeTokenTransfer (opens in a new tab) हुक वापरत आहोत.

1pragma solidity ^0.6.0;
2
3import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
4import "@openzeppelin/contracts/access/Ownable.sol";
5
6contract PrivateERC20 is ERC20, Ownable {
7 mapping (address => bool) public isPrivateUser;
8 uint256 private publicAfterTime;
9
10 constructor(uint256 privateERC20timeInSec) ERC20("PrivateERC20", "PRIV") public {
11 publicAfterTime = now + privateERC20timeInSec;
12 }
13
14 function addUser(address user) external onlyOwner {
15 isPrivateUser[user] = true;
16 }
17
18 function isPublic() public view returns (bool) {
19 return now >= publicAfterTime;
20 }
21
22 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
23 super._beforeTokenTransfer(from, to, amount);
24
25 require(_validRecipient(to), "PrivateERC20: invalid recipient");
26 }
27
28 function _validRecipient(address to) private view returns (bool) {
29 if (isPublic()) {
30 return true;
31 }
32
33 return isPrivateUser[to];
34 }
35}
सर्व दाखवा

आणि आता आपण ते मॉक करूया.

1pragma solidity ^0.6.0;
2import "../PrivateERC20.sol";
3
4contract PrivateERC20Mock is PrivateERC20 {
5 bool isPublicConfig;
6
7 constructor() public PrivateERC20(0) {}
8
9 function setIsPublic(bool isPublic) external {
10 isPublicConfig = isPublic;
11 }
12
13 function isPublic() public view returns (bool) {
14 return isPublicConfig;
15 }
16}
सर्व दाखवा

तुम्हाला खालीलपैकी एक त्रुटी संदेश मिळेल:

  • PrivateERC20Mock.sol: TypeError: Overriding function is missing "override" specifier.
  • PrivateERC20.sol: TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?.

आपण नवीन Solidity आवृत्ती 0.6 वापरत असल्यामुळे, ओव्हरराइड केल्या जाऊ शकणार्‍या फंक्शन्ससाठी virtual कीवर्ड आणि ओव्हरराइडिंग फंक्शनसाठी override कीवर्ड जोडावा लागेल. तर चला, हे दोन्ही isPublic फंक्शन्समध्ये जोडूया.

आता तुमच्या युनिट चाचण्यांमध्ये, तुम्ही त्याऐवजी PrivateERC20Mock वापरू शकता. जेव्हा तुम्हाला खाजगी वापराच्या वेळेतील वर्तनाची चाचणी करायची असेल, तेव्हा setIsPublic(false) वापरा आणि त्याचप्रमाणे सार्वजनिक वापराच्या वेळेची चाचणी करण्यासाठी setIsPublic(true) वापरा. अर्थातच आपल्या उदाहरणात, आपण वेळ बदलण्यासाठी टाइम हेल्पर्स (opens in a new tab) देखील वापरू शकलो असतो. पण आता मॉक करण्याची कल्पना स्पष्ट झाली असेल आणि तुम्ही अशा परिस्थितीची कल्पना करू शकता जिथे फक्त वेळ पुढे नेण्याइतके सोपे नसते.

अनेक कॉन्ट्रॅक्ट्सना मॉक करणे

प्रत्येक मॉकसाठी तुम्हाला दुसरा कॉन्ट्रॅक्ट तयार करावा लागल्यास ते गोंधळात टाकणारे असू शकते. जर तुम्हाला याचा त्रास होत असेल, तर तुम्ही MockContract (opens in a new tab) लायब्ररी पाहू शकता. हे तुम्हाला कॉन्ट्रॅक्ट्सचे वर्तन त्वरित ओव्हरराइड आणि बदलण्याची परवानगी देते. तथापि, हे फक्त दुसऱ्या कॉन्ट्रॅक्टला कॉल मॉक करण्यासाठी कार्य करते, त्यामुळे ते आपल्या उदाहरणासाठी कार्य करणार नाही.

मॉक करणे आणखी शक्तिशाली असू शकते

मॉक करण्याची शक्ती इथेच संपत नाही.

  • फंक्शन्स जोडणे: केवळ एखादे विशिष्ट फंक्शन ओव्हरराइड करणेच उपयुक्त नाही, तर अतिरिक्त फंक्शन्स जोडणे देखील उपयुक्त आहे. टोकन्ससाठी एक चांगले उदाहरण म्हणजे फक्त एक अतिरिक्त mint फंक्शन असणे जे कोणत्याही वापरकर्त्याला विनामूल्य नवीन टोकन मिळविण्याची परवानगी देते.
  • टेस्टनेटमध्ये वापर: जेव्हा तुम्ही तुमच्या dApp सह टेस्टनेटवर तुमचे कॉन्ट्रॅक्ट्स तैनात आणि चाचणी करता, तेव्हा मॉक केलेली आवृत्ती वापरण्याचा विचार करा. खरोखरच गरज असल्याशिवाय फंक्शन्स ओव्हरराइड करणे टाळा. शेवटी, तुम्हाला खऱ्या लॉजिकची चाचणी करायची आहे. परंतु उदाहरणार्थ, रीसेट फंक्शन जोडणे उपयुक्त ठरू शकते जे फक्त कॉन्ट्रॅक्टची स्थिती सुरुवातीला रीसेट करते, नवीन तैनातीची आवश्यकता नाही. अर्थातच तुम्हाला Mainnet कॉन्ट्रॅक्टमध्ये ते नको असेल.

पृष्ठ अखेरचे अद्यतन: २५ ऑगस्ट, २०२५

हे मार्गदर्शन उपयुक्त होते का?