4 releases

0.0.5 Oct 11, 2024
0.0.4 Oct 11, 2024
0.0.3 Oct 11, 2024
0.0.2 Sep 19, 2024

#4 in #inter-chain

Download history 147/week @ 2024-09-16 15/week @ 2024-09-23 13/week @ 2024-09-30 420/week @ 2024-10-07 63/week @ 2024-10-14

155 downloads per month

Apache-2.0

230KB
4.5K SLoC

WARNING: This is an API preview! Expect major bugs, glaring omissions, and breaking changes!

This crate provides a testing framework for Interchain SDK applications using the [ixc] crate. See that crate for more information on getting started.

Getting Started

This framework allows you to write tests for [ixc] handlers using regular rust #[test] functions following these basic steps:

  1. Add a use ixc::testing::* statement (optional, but recommended)
  2. Define a TestApp
  3. Register the handler types we want to test
  4. Create account instances for real or mao
  5. Perform actions on the accounts and assert the results

Let's define a simple counter with one method inc which increments the counter and returns the new value:

#[ixc::handler(Counter)]
pub mod counter {
    use ixc::*;

    #[derive(Resources)]
    pub struct Counter {
        #[state]
        value: Item<u64>,
    }

    #[publish]
    impl Counter {
        #[on_create]
        pub fn create(&self, ctx: &mut Context) -> Result<()> { Ok(()) }

        pub fn inc(&self, ctx: &mut Context) -> Result<u64> {
            let value = self.value.get(ctx)?;
            let new_value = value.checked_add(1).ok_or(
                error!("overflow when incrementing counter")
            )?;
            self.value.set(ctx, new_value)?;
            Ok(new_value)
        }
    }
}

Now we can write a test for this counter. This simple test will create a new counter, increment it and check the result.

#[cfg(test)]
mod tests {
    use super::counter::*;
    use ixc_testing::*;

    #[test]
    fn test_counter() {
        // create the test app
        let mut app = TestApp::default();
        // register the Counter handler type
        app.register_handler::<Counter>().unwrap();
        // create a new client context for a random user Alice
        let mut alice_ctx = app.new_client_context().unwrap();
        // Alice creates a new counter account 
        let counter_client = create_account::<Counter>(&mut alice_ctx, CounterCreate {}).unwrap();
        // Alice increments the counter
        let value = counter_client.inc(&mut alice_ctx).unwrap();
        assert_eq!(value, 1);
        // Alice increments the counter again
        let value = counter_client.inc(&mut alice_ctx).unwrap();
        assert_eq!(value, 2);
    }
}

Using Mocks

Mock handlers created by frameworks such as mockall can be used to test the behavior of a handler in isolation. The MockHandler type can be used to register boxed mock instances of one or more ixc::handler_api traits. And the TestApp::add_mock method can be used to add a mock handler to the test app.

See the examples/ directory in the [ixc] crate for more examples on usage.

Dependencies

~6MB
~116K SLoC