Below are some steps you can take to get the tests working similar to the tutorial referenced.
- Clone down the substrate-node-template:
git clone https://github.com/substrate-developer-hub/substrate-node-template
- Create a
MaxValue
constant in your pallet's runtime:
pallets/template/src/lib.rs
#[pallet::config]
pub trait Config: frame_system::Config {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
#[pallet::constant]
type MaxValue: Get<u32>;
}
- Create a
Total
storage item:
pallets/template/src/lib.rs
#[pallet::storage]
#[pallet::getter(fn total)]
pub type Total<T> = StorageValue<_, u32>;
- Create a
TotalUpdated
event:
pallets/template/src/lib.rs
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Event documentation should end with an array that provides descriptive names for event
/// parameters. [something, who]
TotalUpdated(u32, T::AccountId),
}
- Create a
ValueBiggerThanMax
error:
pallets/template/src/lib.rs
#[pallet::error]
pub enum Error<T> {
/// Errors should have helpful documentation associated with them.
StorageOverflow,
/// Value must be <= MaxValue constant
ValueBiggerThanMax
}
- Create the
add_value
function:
pallets/template/src/lib.rs
#[pallet::weight(10_000 + T::DbWeight::get().writes(1))]
pub fn add_value(origin: OriginFor<T>, value: u32) -> DispatchResult {
let who = ensure_signed(origin)?;
ensure!(value <= T::MaxValue::get(), Error::<T>::ValueBiggerThanMax);
// Read the total from storage.
match <Total<T>>::get() {
// Return an error if there is no total.
None => {
// If None, set storage to value
<Total<T>>::put(value);
// Emit an event.
Self::deposit_event(Event::TotalUpdated(value, who));
// Return a successful DispatchResultWithPostInfo
Ok(())
},
// If total already exists, then get sum of value and total
Some(curr_total) => {
// Add the value to total
let new_total = curr_total.checked_add(value).ok_or(Error::<T>::StorageOverflow)?;
// Update the total in storage
<Total<T>>::put(new_total);
// Emit an event.
Self::deposit_event(Event::TotalUpdated(new_total, who));
// Return a successful DispatchResultWithPostInfo
Ok(())
},
}
}
- Okay now let's setup the mock for our tests. Let's give our pallet a name so we can reference it in our mock file. Add this to line 1 of our mock file:
pallets/template/src/mock.rs
use crate as pallet_template;
- Next let's configure our pallet to work with our mock:
pallets/template/src/mock.rs
frame_support::parameter_types! {
pub const MaxValue: u32 = 50;
}
impl pallet_template::Config for Test {
type Event = Event;
type MaxValue = MaxValue;
}
- And configure the mock runtime to work with our pallet:
pallets/template/src/mock.rs
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
TemplateModule: pallet_template::{Pallet, Call, Storage, Event<T>},
}
);
- Create the tests!
pallets/template/src/tests.rs
use crate::{mock::*, Error};
use frame_support::{assert_ok, assert_err};
#[test]
fn test_add_value() {
new_test_ext().execute_with(|| {
assert_ok!(TestingPallet::add_value(Origin::signed(1), 10));
assert_eq!(TestingPallet::total(), Some(10));
})
}
#[test]
fn test_multiple_add_value() {
new_test_ext().execute_with(|| {
assert_ok!(TestingPallet::add_value(Origin::signed(1), 10));
assert_ok!(TestingPallet::add_value(Origin::signed(1), 20));
assert_eq!(TestingPallet::total(), Some(30));
})
}
#[test]
fn test_max_value() {
new_test_ext().execute_with(|| {
assert_err!(
TestingPallet::add_value(Origin::signed(1), 51),
Error::<Test>::ValueBiggerThanMax
);
})
}
- Finally, in our runtime let's make sure we support the
MaxValue
that we created in our config earlier.
runtime/src/lib.rs
parameter_types! {
pub const MaxValue: u32 = 50;
}
/// Configure the pallet-template in pallets/template.
impl pallet_template::Config for Runtime {
type Event = Event;
type MaxValue = MaxValue;
}
We can now test by running the following command:
cargo test
You should get some green like this:
test tests::test_max_value ... ok
test tests::test_add_value ... ok
test tests::test_multiple_add_value ... ok
Full working code here.