Testing Smart Contracts¶
Hello World Testing¶
Boilerplate greatly simplifies unit testing. This tutorial will test the Hello World contract for reference.
Execute this command to locate AElf.Contracts.HelloWorldContract.Test :
cd ../../test/AElf.Contracts.HelloWorldContract.Tests/
Execute this command to test the Hello World contract:
dotnet test
The following output suggests successful execution of the program:
Test Run Successful. Total tests: 1 Passed: 1 Total time: 2.8865 Seconds
Customize Testing¶
The above instructions explain how to test the built-in contracts in Boilerplate, using Hello World as an example. The following section will expand on this and show you how to test your contracts.
AElf Contract TestKit is a testing framework specifically used to test AElf smart contracts. With this framework, you can simulate the execution of a transaction by constructing a stub of a smart contract and using the methods provided by the Stub instance (corresponding to the contract’s Actions methods) and query (corresponding to the Views methods of the contract), and then get the transaction execution results in the test case.
Test project¶
AElf Boilerplate’s code generator has automatically generated test project for you, you just need to add your test cases.
As you can see, tests are placed in the test folder. Each test folder usually contains a project file (.csproj) and at least four .cs files. The project file is a basic C# xUnit test project file, to which we’ve added some references.
.
└── chain
├── contract
├── protobuf
├── src
└── test
├── AElf.Contracts.GreeterContract.Tests
│ ├── AElf.Contracts.GreeterContract.Tests.csproj // xUnit test project
│ ├── GreeterContractTestBase.cs
│ ├── GreeterContractTestModule.cs
│ └── GreeterContractTests.cs
│ └── GreeterContractInitializationProvider.cs
└── ...
Test your contract¶
Now for the easy part, the test class only needs to inherit from the test base. After this you can go ahead and create the test cases you need.
GreeterContractTest.cs
public class GreeterContractTests : GreeterContractTestBase
{
// declare the method as a xUnit test method
[Fact]
public async Task GreetTest()
{
// Use the contracts stub to call the 'Greet' method and get a reference to
// the transaction result.
var txResult = await GetGreeterContractStub(_defaultKeyPair).Greet.SendAsync(new Empty());
// check that the transaction was mined
txResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined);
// parse the result (return from the contract)
var text = new StringValue();
text.MergeFrom(txResult.TransactionResult.ReturnValue);
// check that the value is correct
text.Value.ShouldBe("Hello World!");
}
// ...
}
From the previous code snippet you can note several things: - the test case is a classic xUnit test class. - you can use the contracts stub to call the contract and check returns.
Feel free to have a look at the full test class in the Boilerplate source code.