运行 基板抛出测试 每个活动托盘在运行时都有一个名称
Running test on substrate throws Every active pallet has a name in the runtime
mock.rs
文件
use crate as pallet_my;
use sp_core::H256;
use frame_support::parameter_types;
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup}, testing::Header,
};
use frame_system as system;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Module, Call, Config, Storage, Event<T>},
MyModule: pallet_my::{Module, Call, Storage, Event<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 42;
}
impl frame_system::Config for Test {
type BaseCallFilter = ();
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Call = Call;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = SS58Prefix;
}
parameter_types! {
pub const MinimumPeriod: u64 = 5;
}
impl pallet_timestamp::Config for Test {
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = ();
type WeightInfo = ();
}
impl pallet_my::Config for Test {
type Event = Event;
type TimeProvider = pallet_timestamp::Pallet<Test>;
}
// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
}
tests.rs
文件
use super::*;
use crate::mock::new_test_ext;
use crate::mock::Origin;
use frame_support::{assert_ok};
use crate::mock::MyModule;
#[test]
fn check_doc_insertion() {
new_test_ext().execute_with(||{
assert_ok!(
MyModule::insert_my_document(Origin::signed(1), vec![1,2,3,4], vec![1,2])
);
});
}
lib.rs
文件托盘配置声明
#[pallet::config]
pub trait Config: frame_system::Config + pallet_timestamp::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
type TimeProvider: UnixTime;
}
插入函数
#[pallet::weight(0)]
pub fn insert_my_document(
origin: OriginFor<T>,
my_document: Vec<u8>,
my_hash: Vec<u8>,
) -> DispatchResultWithPostInfo {
let origin_account = ensure_signed(origin)?;
let block_number = <frame_system::Module<T>>::block_number();
let time = T::TimeProvider::now().as_secs();
myDocument::<T>::insert(
my_hash.clone(),
my {
my_uri: None,
my_document,
block_number,
block_time_stamp: time,
my_ref: None,
sender_account_id: origin_account.clone(),
active: Some(true)
}
);
Self::deposit_event(Event::myDocumentCreated(my_hash, origin_account));
Ok(().into())
}
}
测试抛出一个错误说
Every active pallet has a name in the runtime; qed
thread 'tests::check_doc_insertion' panicked at 'Every active pallet has a name in the runtime; qed'
如何解决这个问题?
您需要将 pallet_timestamp
添加到您的 construct_runtime!
。
// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Module, Call, Config, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
MyModule: pallet_my::{Module, Call, Storage, Event<T>},
}
);
基本上,我们现在希望每个 pallet 都包含在 construct_runtime!
中,它会生成一个 Pallet
结构和一些东西,例如内部元数据的 pallet 名称。
因为您使用的是时间戳托盘,但没有将其正确包含到您的运行时中,所以您会收到此错误。
mock.rs
文件
use crate as pallet_my;
use sp_core::H256;
use frame_support::parameter_types;
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup}, testing::Header,
};
use frame_system as system;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Module, Call, Config, Storage, Event<T>},
MyModule: pallet_my::{Module, Call, Storage, Event<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 42;
}
impl frame_system::Config for Test {
type BaseCallFilter = ();
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Call = Call;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = SS58Prefix;
}
parameter_types! {
pub const MinimumPeriod: u64 = 5;
}
impl pallet_timestamp::Config for Test {
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = ();
type WeightInfo = ();
}
impl pallet_my::Config for Test {
type Event = Event;
type TimeProvider = pallet_timestamp::Pallet<Test>;
}
// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
}
tests.rs
文件
use super::*;
use crate::mock::new_test_ext;
use crate::mock::Origin;
use frame_support::{assert_ok};
use crate::mock::MyModule;
#[test]
fn check_doc_insertion() {
new_test_ext().execute_with(||{
assert_ok!(
MyModule::insert_my_document(Origin::signed(1), vec![1,2,3,4], vec![1,2])
);
});
}
lib.rs
文件托盘配置声明
#[pallet::config]
pub trait Config: frame_system::Config + pallet_timestamp::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
type TimeProvider: UnixTime;
}
插入函数
#[pallet::weight(0)]
pub fn insert_my_document(
origin: OriginFor<T>,
my_document: Vec<u8>,
my_hash: Vec<u8>,
) -> DispatchResultWithPostInfo {
let origin_account = ensure_signed(origin)?;
let block_number = <frame_system::Module<T>>::block_number();
let time = T::TimeProvider::now().as_secs();
myDocument::<T>::insert(
my_hash.clone(),
my {
my_uri: None,
my_document,
block_number,
block_time_stamp: time,
my_ref: None,
sender_account_id: origin_account.clone(),
active: Some(true)
}
);
Self::deposit_event(Event::myDocumentCreated(my_hash, origin_account));
Ok(().into())
}
}
测试抛出一个错误说
Every active pallet has a name in the runtime; qed
thread 'tests::check_doc_insertion' panicked at 'Every active pallet has a name in the runtime; qed'
如何解决这个问题?
您需要将 pallet_timestamp
添加到您的 construct_runtime!
。
// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Module, Call, Config, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
MyModule: pallet_my::{Module, Call, Storage, Event<T>},
}
);
基本上,我们现在希望每个 pallet 都包含在 construct_runtime!
中,它会生成一个 Pallet
结构和一些东西,例如内部元数据的 pallet 名称。
因为您使用的是时间戳托盘,但没有将其正确包含到您的运行时中,所以您会收到此错误。