Solidity
為什麼 Truffle 的測試框架不會在每次與合約互動後自動檢索公共狀態變數的新值?
我定義了以下簡單的智能合約:
contract LoanApplication { struct Applicant { bytes32 ssn; bool hasApplied; } struct Loan { string loanID; uint applicantCount; uint256 rate; uint term; } mapping (address => Applicant) public applicants; Loan[] public loans; address public loansAdmin; constructor(string[] memory loanIDs) { loansAdmin = msg.sender; for (uint i=0; i < loanIDs.length; i++) { // Create Loan object and append to loans array loans.push(Loan({ loanID: loanIDs[i], applicantCount:0, rate: 10, term: 30 })); } } function receiveApplication(address applicant) external { require( msg.sender == loansAdmin, "Only administrator can receive application" ); require( !applicants[applicant].hasApplied, "Applicant previously applied" ); applicants[applicant].hasApplied = true; } }
這是我的 Javascript 測試:
const LoanAppContract = artifacts.require("LoanApplication"); contract("LoanApplicationTest", accounts => { const loanIDs = ["Loan1", "Loan2", "Loan3"]; beforeEach (async () => { loanApp = await LoanAppContract.new(loanIDs); }); describe("initialization", () => { ... }); describe("register application",() => { it("receive app", async() => { let applicantAddr = accounts[1]; console.log("applicantAddr=" + applicantAddr); let applicant = await loanApp.applicants(applicantAddr); assert.isTrue(!applicant.hasApplied); await loanApp.receiveApplication(applicantAddr, {from: accounts[0]}); let applicantRefreshed = await loanApp.applicants(applicantAddr); //assert.isTrue(applicant.hasApplied); assert.isTrue(applicantRefreshed.hasApplied); }); }); });
我正在嘗試測試契約中的 receiveApplication 函式。貸款管理員
hasApplied
在應用程序對象 corr 中設置標誌。到傳入的地址為真我的問題是針對這些行:
// Obtain applicant let applicant = await loanApp.applicants(applicantAddr); // Verify that hasApplied is set to false assert.isTrue(!applicant.hasApplied);
現在呼叫 receiveApplication 函式。hasApplied 標誌現在設置為 true
await loanApp.receiveApplication(applicantAddr, {from: accounts[0]});
我的問題是這樣的:
為什麼這個測試失敗了?
我期待著
assert.isTrue(applicant.hasApplied)
成功,表明 hasApplied 是真的,但看起來申請人參考是陳舊的?
相反,我必須做
let applicantRefreshed = await loanApp.applicants(applicantAddr); assert.isTrue(applicantRefreshed.hasApplied);
為測試成功。我對 Solidity 和 Javascript 還很陌生——迄今為止,我一直是一名 Python 和 Java 開發人員。
感謝幫助澄清這一點。
我正在使用松露執行我的測試,謝謝
本質上是因為您已經在使用一個抽象層,它可以在您需要時為您提供所需的東西,並在呼叫時為您提供新的值。由合約的抽象實例(
loanApp
在您的情況下)在幕後工作,通過 RPC 呼叫節點以了解狀態並將結果發回給您。這就是為什麼您需要await
並且您不能及時使用該值的原因。智能合約可以由開發人員應用程序/測試環境在外部進行修改,因此嘗試保持某種實時同步並非易事。例如,您可以嘗試Drizzle來執行此操作,但無論如何,它專用於 UI,而不是測試和開發階段。
無論如何,如果您想要一個更簡潔的語法而不需要使用許多臨時變數,您可以編寫如下內容:
let applicantAddr = accounts[1]; console.log("applicantAddr=" + applicantAddr); assert.isTrue(!(await loanApp.applicants(applicantAddr)).hasApplied); await loanApp.receiveApplication(applicantAddr, {from: accounts[0]}); assert.isTrue((await loanApp.applicants(applicantAddr)).hasApplied);