4

I've been writing tests for pallet-kitties and have configured the genesis state inside my mock runtime by setting the storage items for two kitties (one Male and one Female) and their owners (with some balance), that way I can use pre-funded accounts and existing kitties in my tests. So, in mock.rs, I have:

pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
    let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
    GenesisConfig {
        balances: BalancesConfig {
            balances: vec![(1,  10), (2,  10)]
        },
        substrate_kitties: SubstrateKittiesConfig {
            kitties: vec![
                (1, *b"1234567890123456", Gender::Female),
                (2, *b"123456789012345a", Gender::Male)
            ]
        },
        ..Default::default()
    }
        .assimilate_storage(&mut t)
        .unwrap();

    let mut ext = sp_io::TestExternalities::new(t);
    ext.execute_with(|| System::set_block_number(1));
    ext
}

For one of my tests, I need a third, uniquely owned kitty which means I have to add that kitty and a new account in the genesis state of my mock runtime. This doesn't feel like the best approach because I'd be using genesis state for all of my tests — even those that don't need the third kitty.

How can I configure genesis so I can specify genesis state as parameters for my tests instead?

1 Answer 1

5

You can configure the new_test_ext function however you like. In this case, you can make it take the parameters you'll want to use to modify your genesis state and then just pass values into your tests directly. And in mock.rs, all you need to do is abstract the configuration logic:

pub(crate) fn new_test_ext(users: Vec<(u64, [u8; 16], Gender)>) -> sp_io::TestExternalities {
    let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
    GenesisConfig {
        //
        balances: BalancesConfig {
            balances: users.iter().map(|(user, _, _)| (*user, 10)).collect(),
        },
        substrate_kitties: SubstrateKittiesConfig {
            kitties: users.iter().map(|(user, kitty, gender)| (*user, *kitty, *gender)).collect(),
        },
        ..Default::default()
    }
    .assimilate_storage(&mut t)
    .unwrap();

    let mut ext = sp_io::TestExternalities::new(t);
    ext.execute_with(|| System::set_block_number(1));
    ext
}

Then in tests.rs, just specify what you want your state to be for the test you're writing. For example:

#[test]
fn should_build_genesis_kitties() {
    new_test_ext(vec![
        (1, *b"1234567890123456", Gender::Female), // <-- pass in genesis configuration for account #1
        (2, *b"123456789012345a", Gender::Male),   // <-- pass in genesis configuration for account #2
    ])
    .execute_with(|| {
        // Check we have 2 kitties, as specified in genesis
        assert_eq!(CountForKitties::<Test>::get(), 2);
    });
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.