Repository: CosmWasm/cw-multi-test
Pull request #116 (2023-12-18 17:03:52)

Refactoring custom message type constraints
**cosmwasm-std** defines a trait `CustomQuery`:
```rust
pub trait CustomQuery: Serialize + Clone {}
```
used everywhere in **MultiTest** to constrain the custom query type.
In opposite, **MultiTest** does not use `CustomMsg` trait (also defined in **cosmwasm-std**) to constrain custom message type:
```rust
pub trait CustomMsg: Serialize + Clone + Debug + PartialEq + JsonSchema {}
```
This pull request introduces `CustomMsg` in all needed places instead of constraints like this:
```rust
where
    ExecC: Debug + Clone + PartialEq + JsonSchema
```
becomes:
```rust
where
    ExecC: CustomMsg
```
**Multitest** custom message type constraints were lacking `Serialize`, this is fixed by using `CustomMsg`.


Patch:
diff --git a/src/app.rs b/src/app.rs
index 29c9718..77d1f02 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -12,11 +12,10 @@ use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo};
 use crate::{AppBuilder, GovFailingModule, IbcFailingModule};
 use cosmwasm_std::testing::{MockApi, MockStorage};
 use cosmwasm_std::{
-    from_json, to_json_binary, Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg,
+    from_json, to_json_binary, Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg, CustomMsg,
     CustomQuery, Empty, Querier, QuerierResult, QuerierWrapper, QueryRequest, Record, Storage,
     SystemError, SystemResult,
 };
-use schemars::JsonSchema;
 use serde::{de::DeserializeOwned, Serialize};
 use std::fmt::Debug;
 use std::marker::PhantomData;
@@ -107,7 +106,7 @@ impl BasicApp {
 /// Outside of `App` implementation to make type elision better.
 pub fn custom_app<ExecC, QueryC, F>(init_fn: F) -> BasicApp<ExecC, QueryC>
 where
-    ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    ExecC: CustomMsg + DeserializeOwned + 'static,
     QueryC: Debug + CustomQuery + DeserializeOwned + 'static,
     F: FnOnce(
         &mut Router<
@@ -130,7 +129,7 @@ where
 impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT> Querier
     for App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
 where
-    CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
     BankT: Bank,
@@ -154,7 +153,7 @@ impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, Starga
     Executor<CustomT::ExecT>
     for App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
 where
-    CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
     BankT: Bank,
@@ -250,7 +249,7 @@ where
     IbcT: Ibc,
     GovT: Gov,
     StargateT: Stargate,
-    CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
 {
     /// Registers contract code (like uploading wasm bytecode on a chain),
@@ -340,7 +339,7 @@ where
 impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
     App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
 where
-    CustomT::ExecT: Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
     BankT: Bank,
@@ -476,7 +475,7 @@ pub struct Router<Bank, Custom, Wasm, Staking, Distr, Ibc, Gov, Stargate> {
 impl<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
     Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
 where
-    CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     CustomT: Module,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
@@ -576,7 +575,7 @@ pub trait CosmosRouter {
 impl<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT> CosmosRouter
     for Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
 where
-    CustomT::ExecT: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     CustomT: Module,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
@@ -739,7 +738,7 @@ impl<'a, ExecC, QueryC> RouterQuerier<'a, ExecC, QueryC> {
 
 impl<'a, ExecC, QueryC> Querier for RouterQuerier<'a, ExecC, QueryC>
 where
-    ExecC: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    ExecC: CustomMsg + DeserializeOwned + 'static,
     QueryC: CustomQuery + DeserializeOwned + 'static,
 {
     fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
diff --git a/src/app_builder.rs b/src/app_builder.rs
index eb5b782..e8b3d9d 100644
--- a/src/app_builder.rs
+++ b/src/app_builder.rs
@@ -6,8 +6,7 @@ use crate::{
     WasmKeeper,
 };
 use cosmwasm_std::testing::{mock_env, MockApi, MockStorage};
-use cosmwasm_std::{Api, BlockInfo, CustomQuery, Empty, Storage};
-use schemars::JsonSchema;
+use cosmwasm_std::{Api, BlockInfo, CustomMsg, CustomQuery, Empty, Storage};
 use serde::de::DeserializeOwned;
 use std::fmt::Debug;
 
@@ -123,7 +122,7 @@ impl<ExecC, QueryC>
         StargateFailing,
     >
 where
-    ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    ExecC: CustomMsg + DeserializeOwned + 'static,
     QueryC: Debug + CustomQuery + DeserializeOwned + 'static,
 {
     /// Creates builder with default components designed to work with custom exec and query
diff --git a/src/contracts.rs b/src/contracts.rs
index 954f49c..6d7afb2 100644
--- a/src/contracts.rs
+++ b/src/contracts.rs
@@ -2,10 +2,9 @@
 
 use crate::error::{anyhow, bail, AnyError, AnyResult};
 use cosmwasm_std::{
-    from_json, Binary, CosmosMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo,
+    from_json, Binary, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo,
     QuerierWrapper, Reply, Response, SubMsg,
 };
-use schemars::JsonSchema;
 use serde::de::DeserializeOwned;
 use std::error::Error;
 use std::fmt::{Debug, Display};
@@ -17,7 +16,7 @@ use std::ops::Deref;
 /// making it a fundamental trait for testing contracts.
 pub trait Contract<T, Q = Empty>
 where
-    T: Clone + Debug + PartialEq + JsonSchema,
+    T: CustomMsg,
     Q: CustomQuery,
 {
     /// Evaluates contract's `execute` entry-point.
@@ -92,7 +91,7 @@ pub struct ContractWrapper<
     E4: Display + Debug + Send + Sync + 'static,
     E5: Display + Debug + Send + Sync + 'static,
     E6: Display + Debug + Send + Sync + 'static,
-    C: Clone + Debug + PartialEq + JsonSchema,
+    C: CustomMsg,
     Q: CustomQuery + DeserializeOwned + 'static,
 {
     execute_fn: ContractClosure<T1, C, E1, Q>,
@@ -111,7 +110,7 @@ where
     E1: Display + Debug + Send + Sync + 'static,
     E2: Display + Debug + Send + Sync + 'static,
     E3: Display + Debug + Send + Sync + 'static,
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
     Q: CustomQuery + DeserializeOwned + 'static,
 {
     /// Creates a new contract wrapper with default settings.
@@ -162,7 +161,7 @@ where
     E4: Display + Debug + Send + Sync + 'static,
     E5: Display + Debug + Send + Sync + 'static,
     E6: Display + Debug + Send + Sync + 'static,
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
     Q: CustomQuery + DeserializeOwned + 'static,
 {
     /// Populates [ContractWrapper] with contract's `sudo` entry-point and custom message type.
@@ -282,7 +281,7 @@ fn customize_fn<T, C, E, Q>(raw_fn: ContractFn<T, Empty, E, Empty>) -> ContractC
 where
     T: DeserializeOwned + 'static,
     E: Display + Debug + Send + Sync + 'static,
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
     Q: CustomQuery + DeserializeOwned + 'static,
 {
     let customized = move |mut deps: DepsMut<Q>,
@@ -337,7 +336,7 @@ fn customize_permissioned_fn<T, C, E, Q>(
 where
     T: DeserializeOwned + 'static,
     E: Display + Debug + Send + Sync + 'static,
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
     Q: CustomQuery + DeserializeOwned + 'static,
 {
     let customized = move |deps: DepsMut<Q>, env: Env, msg: T| -> Result<Response<C>, E> {
@@ -348,7 +347,7 @@ where
 
 fn customize_response<C>(resp: Response<Empty>) -> Response<C>
 where
-    C: Clone + Debug + PartialEq + JsonSchema,
+    C: CustomMsg,
 {
     let mut customized_resp = Response::<C>::new()
         .add_submessages(resp.messages.into_iter().map(customize_msg::<C>))
@@ -360,7 +359,7 @@ where
 
 fn customize_msg<C>(msg: SubMsg<Empty>) -> SubMsg<C>
 where
-    C: Clone + Debug + PartialEq + JsonSchema,
+    C: CustomMsg,
 {
     SubMsg {
         msg: match msg.msg {
@@ -393,7 +392,7 @@ where
     E4: Display + Debug + Send + Sync + 'static,
     E5: Display + Debug + Send + Sync + 'static,
     E6: Display + Debug + Send + Sync + 'static,
-    C: Clone + Debug + PartialEq + JsonSchema,
+    C: CustomMsg,
     Q: CustomQuery + DeserializeOwned,
 {
     fn execute(
diff --git a/src/executor.rs b/src/executor.rs
index d5932ca..0e80f17 100644
--- a/src/executor.rs
+++ b/src/executor.rs
@@ -1,10 +1,9 @@
 use crate::error::AnyResult;
 use cosmwasm_std::{
-    to_json_binary, Addr, Attribute, BankMsg, Binary, Coin, CosmosMsg, Event, SubMsgResponse,
-    WasmMsg,
+    to_json_binary, Addr, Attribute, BankMsg, Binary, Coin, CosmosMsg, CustomMsg, Event,
+    SubMsgResponse, WasmMsg,
 };
 use cw_utils::{parse_execute_response_data, parse_instantiate_response_data};
-use schemars::JsonSchema;
 use serde::Serialize;
 use std::fmt::Debug;
 
@@ -71,7 +70,7 @@ impl From<SubMsgResponse> for AppResponse {
 /// flow and ensuring that contract _calls_ are processed correctly.
 pub trait Executor<C>
 where
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
 {
     /// Processes (executes) an arbitrary `CosmosMsg`.
     /// This will create a cache before the execution,
diff --git a/src/module.rs b/src/module.rs
index aac82ba..cc73a4d 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -1,8 +1,7 @@
 use crate::app::CosmosRouter;
 use crate::error::{bail, AnyResult};
 use crate::AppResponse;
-use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomQuery, Querier, Storage};
-use schemars::JsonSchema;
+use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Querier, Storage};
 use serde::de::DeserializeOwned;
 use std::fmt::Debug;
 use std::marker::PhantomData;
@@ -33,7 +32,7 @@ pub trait Module {
         msg: Self::ExecT,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static;
 
     /// Runs any [QueryT](Self::QueryT) message,
@@ -61,7 +60,7 @@ pub trait Module {
         msg: Self::SudoT,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static;
 }
 /// # Always failing module
diff --git a/src/stargate.rs b/src/stargate.rs
index b8127c2..a91dc89 100644
--- a/src/stargate.rs
+++ b/src/stargate.rs
@@ -1,10 +1,8 @@
 use crate::error::AnyResult;
 use crate::{AppResponse, CosmosRouter};
 use anyhow::bail;
-use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomQuery, Querier, Storage};
-use schemars::JsonSchema;
+use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Querier, Storage};
 use serde::de::DeserializeOwned;
-use std::fmt::Debug;
 
 /// Stargate interface.
 ///
@@ -27,7 +25,7 @@ pub trait Stargate {
         value: Binary,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static,
     {
         let _ = (api, storage, router, block);
@@ -83,7 +81,7 @@ impl Stargate for StargateAccepting {
         value: Binary,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static,
     {
         let _ = (api, storage, router, block, sender, type_url, value);
diff --git a/src/wasm.rs b/src/wasm.rs
index 5ea2e96..9e313c9 100644
--- a/src/wasm.rs
+++ b/src/wasm.rs
@@ -9,9 +9,9 @@ use crate::transactions::transactional;
 use cosmwasm_std::testing::mock_wasmd_attr;
 use cosmwasm_std::{
     to_json_binary, Addr, Api, Attribute, BankMsg, Binary, BlockInfo, Coin, ContractInfo,
-    ContractInfoResponse, CustomQuery, Deps, DepsMut, Env, Event, HexBinary, MessageInfo, Order,
-    Querier, QuerierWrapper, Record, Reply, ReplyOn, Response, StdResult, Storage, SubMsg,
-    SubMsgResponse, SubMsgResult, TransactionInfo, WasmMsg, WasmQuery,
+    ContractInfoResponse, CustomMsg, CustomQuery, Deps, DepsMut, Env, Event, HexBinary,
+    MessageInfo, Order, Querier, QuerierWrapper, Record, Reply, ReplyOn, Response, StdResult,
+    Storage, SubMsg, SubMsgResponse, SubMsgResult, TransactionInfo, WasmMsg, WasmQuery,
 };
 use cw_storage_plus::Map;
 use prost::Message;
@@ -154,7 +154,7 @@ impl<ExecC, QueryC> Default for WasmKeeper<ExecC, QueryC> {
 
 impl<ExecC, QueryC> Wasm<ExecC, QueryC> for WasmKeeper<ExecC, QueryC>
 where
-    ExecC: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    ExecC: CustomMsg + DeserializeOwned + 'static,
     QueryC: CustomQuery + DeserializeOwned + 'static,
 {
     fn query(
@@ -341,7 +341,7 @@ impl<ExecC, QueryC> WasmKeeper<ExecC, QueryC> {
 
     fn verify_response<T>(response: Response<T>) -> AnyResult<Response<T>>
     where
-        T: Clone + Debug + PartialEq + JsonSchema,
+        T: CustomMsg,
     {
         Self::verify_attributes(&response.attributes)?;
 
@@ -359,7 +359,7 @@ impl<ExecC, QueryC> WasmKeeper<ExecC, QueryC> {
 
 impl<ExecC, QueryC> WasmKeeper<ExecC, QueryC>
 where
-    ExecC: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    ExecC: CustomMsg + DeserializeOwned + 'static,
     QueryC: CustomQuery + DeserializeOwned + 'static,
 {
     /// Creates a wasm keeper with default settings.


Test patch:
diff --git a/src/test_helpers/caller.rs b/src/test_helpers/caller.rs
index c283cda..1d50a62 100644
--- a/src/test_helpers/caller.rs
+++ b/src/test_helpers/caller.rs
@@ -1,9 +1,7 @@
 use crate::{Contract, ContractWrapper};
 use cosmwasm_std::{
-    Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg,
+    Binary, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg,
 };
-use schemars::JsonSchema;
-use std::fmt::Debug;
 
 fn instantiate(
     _deps: DepsMut,
@@ -33,7 +31,7 @@ fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result<Binary, StdError> {
 
 pub fn contract<C>() -> Box<dyn Contract<C>>
 where
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
 {
     let contract = ContractWrapper::new_with_empty(execute, instantiate, query);
     Box::new(contract)
diff --git a/src/test_helpers/echo.rs b/src/test_helpers/echo.rs
index 02ab269..0b73a39 100644
--- a/src/test_helpers/echo.rs
+++ b/src/test_helpers/echo.rs
@@ -5,8 +5,8 @@
 
 use crate::{Contract, ContractWrapper};
 use cosmwasm_std::{
-    to_json_binary, Attribute, Binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply,
-    Response, StdError, SubMsg, SubMsgResponse, SubMsgResult,
+    to_json_binary, Attribute, Binary, CustomMsg, Deps, DepsMut, Empty, Env, Event, MessageInfo,
+    Reply, Response, StdError, SubMsg, SubMsgResponse, SubMsgResult,
 };
 use cw_utils::{parse_execute_response_data, parse_instantiate_response_data};
 use derivative::Derivative;
@@ -130,7 +130,7 @@ pub fn contract() -> Box<dyn Contract<Empty>> {
 
 pub fn custom_contract<C>() -> Box<dyn Contract<C>>
 where
-    C: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    C: CustomMsg + DeserializeOwned + 'static,
 {
     let contract =
         ContractWrapper::new(execute::<C>, instantiate::<C>, query).with_reply(reply::<C>);
diff --git a/src/test_helpers/error.rs b/src/test_helpers/error.rs
index 033853d..1654440 100644
--- a/src/test_helpers/error.rs
+++ b/src/test_helpers/error.rs
@@ -1,7 +1,5 @@
 use crate::{Contract, ContractWrapper};
-use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError};
-use schemars::JsonSchema;
-use std::fmt::Debug;
+use cosmwasm_std::{Binary, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError};
 
 fn instantiate_err(
     _deps: DepsMut,
@@ -36,7 +34,7 @@ fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result<Binary, StdError> {
 
 pub fn contract<C>(instantiable: bool) -> Box<dyn Contract<C>>
 where
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
 {
     let contract = if instantiable {
         ContractWrapper::new_with_empty(execute, instantiate_ok, query)
diff --git a/src/test_helpers/hackatom.rs b/src/test_helpers/hackatom.rs
index 394c735..34d4f1e 100644
--- a/src/test_helpers/hackatom.rs
+++ b/src/test_helpers/hackatom.rs
@@ -2,10 +2,10 @@
 
 use crate::{Contract, ContractWrapper};
 use cosmwasm_std::{
-    to_json_binary, BankMsg, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError,
+    to_json_binary, BankMsg, Binary, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response,
+    StdError,
 };
 use cw_storage_plus::Item;
-use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
 use std::fmt::Debug;
 
@@ -77,7 +77,7 @@ pub fn contract() -> Box<dyn Contract<Empty>> {
 #[allow(dead_code)]
 pub fn custom_contract<C>() -> Box<dyn Contract<C>>
 where
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
 {
     let contract =
         ContractWrapper::new_with_empty(execute, instantiate, query).with_migrate_empty(migrate);
diff --git a/src/test_helpers/mod.rs b/src/test_helpers/mod.rs
index 16d2308..d6ee1ad 100644
--- a/src/test_helpers/mod.rs
+++ b/src/test_helpers/mod.rs
@@ -1,5 +1,6 @@
 #![cfg(test)]
 
+use cosmwasm_std::CustomMsg;
 use cw_storage_plus::Item;
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
@@ -17,10 +18,12 @@ pub mod stargate;
 /// Custom message for testing purposes.
 #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 #[serde(rename = "snake_case")]
-pub enum CustomMsg {
+pub enum CustomHelperMsg {
     SetName { name: String },
     SetAge { age: u32 },
 }
 
+impl CustomMsg for CustomHelperMsg {}
+
 /// Persisted counter for testing purposes.
 pub const COUNT: Item<u32> = Item::new("count");
diff --git a/src/test_helpers/payout.rs b/src/test_helpers/payout.rs
index a1d13ea..159f6ce 100644
--- a/src/test_helpers/payout.rs
+++ b/src/test_helpers/payout.rs
@@ -1,11 +1,10 @@
 use crate::test_helpers::COUNT;
 use crate::{Contract, ContractWrapper};
 use cosmwasm_std::{
-    to_json_binary, BankMsg, Binary, Coin, Deps, DepsMut, Empty, Env, MessageInfo, Response,
-    StdError,
+    to_json_binary, BankMsg, Binary, Coin, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo,
+    Response, StdError,
 };
 use cw_storage_plus::Item;
-use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
 use std::fmt::Debug;
 
@@ -76,7 +75,7 @@ fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, StdError> {
 
 pub fn contract<C>() -> Box<dyn Contract<C>>
 where
-    C: Clone + Debug + PartialEq + JsonSchema + 'static,
+    C: CustomMsg + 'static,
 {
     let contract =
         ContractWrapper::new_with_empty(execute, instantiate, query).with_sudo_empty(sudo);
diff --git a/src/test_helpers/reflect.rs b/src/test_helpers/reflect.rs
index c7b3740..41b4396 100644
--- a/src/test_helpers/reflect.rs
+++ b/src/test_helpers/reflect.rs
@@ -1,4 +1,4 @@
-use crate::test_helpers::{payout, CustomMsg, COUNT};
+use crate::test_helpers::{payout, CustomHelperMsg, COUNT};
 use crate::{Contract, ContractWrapper};
 use cosmwasm_std::{
     to_json_binary, Binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply, Response,
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
 
 #[derive(Debug, Clone, Serialize, Deserialize, Default)]
 pub struct Message {
-    pub messages: Vec<SubMsg<CustomMsg>>,
+    pub messages: Vec<SubMsg<CustomHelperMsg>>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -25,7 +25,7 @@ fn instantiate(
     _env: Env,
     _info: MessageInfo,
     _msg: Empty,
-) -> Result<Response<CustomMsg>, StdError> {
+) -> Result<Response<CustomHelperMsg>, StdError> {
     COUNT.save(deps.storage, &0)?;
     Ok(Response::default())
 }
@@ -35,7 +35,7 @@ fn execute(
     _env: Env,
     _info: MessageInfo,
     msg: Message,
-) -> Result<Response<CustomMsg>, StdError> {
+) -> Result<Response<CustomHelperMsg>, StdError> {
     COUNT.update::<_, StdError>(deps.storage, |old| Ok(old + 1))?;
 
     Ok(Response::new().add_submessages(msg.messages))
@@ -55,7 +55,7 @@ fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<Binary, StdError> {
     }
 }
 
-fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result<Response<CustomMsg>, StdError> {
+fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result<Response<CustomHelperMsg>, StdError> {
     REFLECT.save(deps.storage, msg.id, &msg)?;
     // add custom event here to test
     let event = Event::new("custom")
@@ -64,7 +64,7 @@ fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result<Response<CustomMsg>, St
     Ok(Response::new().add_event(event))
 }
 
-pub fn contract() -> Box<dyn Contract<CustomMsg>> {
+pub fn contract() -> Box<dyn Contract<CustomHelperMsg>> {
     let contract = ContractWrapper::new(execute, instantiate, query).with_reply(reply);
     Box::new(contract)
 }
diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs
index f6d41f1..46f33db 100644
--- a/src/tests/test_app.rs
+++ b/src/tests/test_app.rs
@@ -1,7 +1,7 @@
 use crate::custom_handler::CachingCustomHandler;
 use crate::error::{bail, AnyResult};
 use crate::test_helpers::echo::EXECUTE_REPLY_BASE_ID;
-use crate::test_helpers::{caller, echo, error, hackatom, payout, reflect, CustomMsg};
+use crate::test_helpers::{caller, echo, error, hackatom, payout, reflect, CustomHelperMsg};
 use crate::transactions::{transactional, StorageTransaction};
 use crate::wasm::ContractData;
 use crate::AppBuilder;
@@ -12,8 +12,9 @@ use crate::{
 use cosmwasm_std::testing::{mock_env, MockQuerier};
 use cosmwasm_std::{
     coin, coins, from_json, to_json_binary, Addr, AllBalanceResponse, Api, Attribute, BankMsg,
-    BankQuery, Binary, BlockInfo, Coin, CosmosMsg, CustomQuery, Empty, Event, OverflowError,
-    OverflowOperation, Querier, Reply, StdError, StdResult, Storage, SubMsg, WasmMsg,
+    BankQuery, Binary, BlockInfo, Coin, CosmosMsg, CustomMsg, CustomQuery, Empty, Event,
+    OverflowError, OverflowOperation, Querier, Reply, StdError, StdResult, Storage, SubMsg,
+    WasmMsg,
 };
 use cw_storage_plus::Item;
 use cw_utils::parse_instantiate_response_data;
@@ -28,7 +29,7 @@ fn get_balance<BankT, ApiT, StorageT, CustomT, WasmT>(
     addr: &Addr,
 ) -> Vec<Coin>
 where
-    CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
     BankT: Bank,
@@ -46,7 +47,7 @@ fn query_router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>(
     rcpt: &Addr,
 ) -> Vec<Coin>
 where
-    CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema,
+    CustomT::ExecT: CustomMsg,
     CustomT::QueryT: CustomQuery + DeserializeOwned,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
     BankT: Bank,
@@ -72,7 +73,7 @@ fn query_app<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT>(
     rcpt: &Addr,
 ) -> Vec<Coin>
 where
-    CustomT::ExecT: Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static,
+    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
     CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
     WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
     BankT: Bank,
@@ -324,7 +325,7 @@ fn reflect_success() {
     let owner = Addr::unchecked("owner");
     let init_funds = vec![coin(20, "btc"), coin(100, "eth")];
 
-    let mut app = custom_app::<CustomMsg, Empty, _>(|router, _, storage| {
+    let mut app = custom_app::<CustomHelperMsg, Empty, _>(|router, _, storage| {
         router
             .bank
             .init_balance(storage, &owner, init_funds)
@@ -430,7 +431,7 @@ fn reflect_error() {
     let owner = Addr::unchecked("owner");
     let init_funds = vec![coin(20, "btc"), coin(100, "eth")];
 
-    let mut app = custom_app::<CustomMsg, Empty, _>(|router, _, storage| {
+    let mut app = custom_app::<CustomHelperMsg, Empty, _>(|router, _, storage| {
         router
             .bank
             .init_balance(storage, &owner, init_funds)
@@ -581,7 +582,7 @@ fn reflect_sub_message_reply_works() {
     let random = Addr::unchecked("random");
     let init_funds = vec![coin(20, "btc"), coin(100, "eth")];
 
-    let mut app = custom_app::<CustomMsg, Empty, _>(|router, _, storage| {
+    let mut app = custom_app::<CustomHelperMsg, Empty, _>(|router, _, storage| {
         router
             .bank
             .init_balance(storage, &owner, init_funds)
@@ -855,17 +856,19 @@ mod custom_handler {
     const PITY: Item<Coin> = Item::new("pity");
 
     #[derive(Clone, Debug, PartialEq, JsonSchema, Serialize, Deserialize)]
-    struct CustomMsg {
+    struct CustomLotteryMsg {
         // we mint LOTTERY tokens to this one
         lucky_winner: String,
         // we transfer PITY from lucky_winner to runner_up
         runner_up: String,
     }
 
+    impl CustomMsg for CustomLotteryMsg {}
+
     struct CustomHandler {}
 
     impl Module for CustomHandler {
-        type ExecT = CustomMsg;
+        type ExecT = CustomLotteryMsg;
         type QueryT = Empty;
         type SudoT = Empty;
 
@@ -879,7 +882,7 @@ mod custom_handler {
             msg: Self::ExecT,
         ) -> AnyResult<AppResponse>
         where
-            ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+            ExecC: CustomMsg + DeserializeOwned + 'static,
             QueryC: CustomQuery + DeserializeOwned + 'static,
         {
             let lottery = LOTTERY.load(storage)?;
@@ -912,7 +915,7 @@ mod custom_handler {
             _msg: Self::SudoT,
         ) -> AnyResult<AppResponse>
         where
-            ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+            ExecC: CustomMsg + DeserializeOwned + 'static,
             QueryC: CustomQuery + DeserializeOwned + 'static,
         {
             bail!("sudo not implemented for CustomHandler")
@@ -955,7 +958,7 @@ mod custom_handler {
         let lottery = coin(54321, denom);
         let bonus = coin(12321, denom);
 
-        let mut app = BasicAppBuilder::<CustomMsg, Empty>::new_custom()
+        let mut app = BasicAppBuilder::<CustomLotteryMsg, Empty>::new_custom()
             .with_custom(CustomHandler {})
             .build(|router, _, storage| {
                 router
@@ -969,7 +972,7 @@ mod custom_handler {
         assert_eq!(start, coin(0, denom));
 
         // trigger the custom module
-        let msg = CosmosMsg::Custom(CustomMsg {
+        let msg = CosmosMsg::Custom(CustomLotteryMsg {
             lucky_winner: winner.clone(),
             runner_up: second.clone(),
         });
@@ -1183,7 +1186,7 @@ mod reply_data_overwrite {
         let owner = Addr::unchecked("owner");
         let init_funds = coins(100, "tgd");
 
-        let mut app = custom_app::<CustomMsg, Empty, _>(|router, _, storage| {
+        let mut app = custom_app::<CustomHelperMsg, Empty, _>(|router, _, storage| {
             router
                 .bank
                 .init_balance(storage, &owner, init_funds)
@@ -1621,7 +1624,7 @@ mod custom_messages {
 
     #[test]
     fn triggering_custom_msg() {
-        let custom_handler = CachingCustomHandler::<CustomMsg, Empty>::new();
+        let custom_handler = CachingCustomHandler::<CustomHelperMsg, Empty>::new();
         let custom_handler_state = custom_handler.state();
 
         let mut app = AppBuilder::new_custom()
@@ -1641,7 +1644,7 @@ mod custom_messages {
             sender,
             contract,
             &echo::Message {
-                sub_msg: vec![SubMsg::new(CosmosMsg::Custom(CustomMsg::SetAge {
+                sub_msg: vec![SubMsg::new(CosmosMsg::Custom(CustomHelperMsg::SetAge {
                     age: 20,
                 }))],
                 ..Default::default()
@@ -1652,7 +1655,7 @@ mod custom_messages {
 
         assert_eq!(
             custom_handler_state.execs().to_owned(),
-            vec![CustomMsg::SetAge { age: 20 }]
+            vec![CustomHelperMsg::SetAge { age: 20 }]
         );
 
         assert!(custom_handler_state.queries().is_empty());
@@ -1669,7 +1672,7 @@ mod protobuf_wrapped_data {
         let owner = Addr::unchecked("owner");
         let init_funds = vec![coin(20, "btc")];
 
-        let mut app = custom_app::<CustomMsg, Empty, _>(|router, _, storage| {
+        let mut app = custom_app::<CustomHelperMsg, Empty, _>(|router, _, storage| {
             router
                 .bank
                 .init_balance(storage, &owner, init_funds)
diff --git a/src/tests/test_custom_handler.rs b/src/tests/test_custom_handler.rs
index 7ded4f7..3616826 100644
--- a/src/tests/test_custom_handler.rs
+++ b/src/tests/test_custom_handler.rs
@@ -1,5 +1,5 @@
 use crate::custom_handler::CachingCustomHandler;
-use crate::test_helpers::CustomMsg;
+use crate::test_helpers::CustomHelperMsg;
 use crate::{App, Module};
 use cosmwasm_std::testing::MockStorage;
 use cosmwasm_std::{Addr, Empty};
@@ -14,7 +14,7 @@ fn custom_handler_works() {
     let mut storage = MockStorage::default();
 
     // create custom handler
-    let custom_handler = CachingCustomHandler::<CustomMsg, CustomMsg>::new();
+    let custom_handler = CachingCustomHandler::<CustomHelperMsg, CustomHelperMsg>::new();
 
     // run execute function
     let _ = custom_handler.execute(
@@ -23,7 +23,7 @@ fn custom_handler_works() {
         app.router(),
         &app.block_info(),
         Addr::unchecked("sender"),
-        CustomMsg::SetAge { age: 32 },
+        CustomHelperMsg::SetAge { age: 32 },
     );
 
     // run query function
@@ -32,7 +32,7 @@ fn custom_handler_works() {
         &storage,
         &(*app.wrap()),
         &app.block_info(),
-        CustomMsg::SetName {
+        CustomHelperMsg::SetName {
             name: "John".to_string(),
         },
     );
@@ -43,13 +43,13 @@ fn custom_handler_works() {
     // there should be one exec message
     assert_eq!(
         custom_handler_state.execs().to_owned(),
-        vec![CustomMsg::SetAge { age: 32 }]
+        vec![CustomHelperMsg::SetAge { age: 32 }]
     );
 
     // there should be one query message
     assert_eq!(
         custom_handler_state.queries().to_owned(),
-        vec![CustomMsg::SetName {
+        vec![CustomHelperMsg::SetName {
             name: "John".to_string()
         }]
     );
@@ -67,7 +67,7 @@ fn custom_handler_has_no_sudo() {
     let mut storage = MockStorage::default();
 
     // create custom handler
-    let custom_handler = CachingCustomHandler::<CustomMsg, CustomMsg>::new();
+    let custom_handler = CachingCustomHandler::<CustomHelperMsg, CustomHelperMsg>::new();
 
     // run sudo function
     assert_eq!(
diff --git a/tests/test_app_builder/mod.rs b/tests/test_app_builder/mod.rs
index 476df22..d2dcc5c 100644
--- a/tests/test_app_builder/mod.rs
+++ b/tests/test_app_builder/mod.rs
@@ -1,7 +1,6 @@
-use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomQuery, Querier, Storage};
+use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Querier, Storage};
 use cw_multi_test::error::{bail, AnyResult};
 use cw_multi_test::{AppResponse, CosmosRouter, Module};
-use schemars::JsonSchema;
 use serde::de::DeserializeOwned;
 use std::fmt::Debug;
 use std::marker::PhantomData;
@@ -52,7 +51,7 @@ where
         _msg: Self::ExecT,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static,
     {
         bail!(self.1);
@@ -67,7 +66,7 @@ where
         _msg: Self::SudoT,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static,
     {
         bail!(self.3);
diff --git a/tests/test_app_builder/test_with_stargate.rs b/tests/test_app_builder/test_with_stargate.rs
index 624e701..65771bd 100644
--- a/tests/test_app_builder/test_with_stargate.rs
+++ b/tests/test_app_builder/test_with_stargate.rs
@@ -1,6 +1,6 @@
 use anyhow::bail;
 use cosmwasm_std::{
-    to_json_vec, Addr, Api, Binary, BlockInfo, CosmosMsg, CustomQuery, Empty, Querier,
+    to_json_vec, Addr, Api, Binary, BlockInfo, CosmosMsg, CustomMsg, CustomQuery, Empty, Querier,
     QueryRequest, Storage,
 };
 use cw_multi_test::error::AnyResult;
@@ -8,9 +8,7 @@ use cw_multi_test::{
     no_init, AppBuilder, AppResponse, CosmosRouter, Executor, Stargate, StargateAccepting,
     StargateFailing,
 };
-use schemars::JsonSchema;
 use serde::de::DeserializeOwned;
-use std::fmt::Debug;
 
 const EXECUTE_MSG: &str = "stargate execute called";
 const QUERY_MSG: &str = "stargate query called";
@@ -30,7 +28,7 @@ impl Stargate for MyStargateKeeper {
         value: Binary,
     ) -> AnyResult<AppResponse>
     where
-        ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static,
+        ExecC: CustomMsg + DeserializeOwned + 'static,
         QueryC: CustomQuery + DeserializeOwned + 'static,
     {
         assert_eq!("test", type_url);