github.com/cosmos/cosmos-sdk@v0.50.10/testutil/integration/example_test.go (about) 1 package integration_test 2 3 import ( 4 "fmt" 5 "io" 6 7 cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" 8 "github.com/google/go-cmp/cmp" 9 10 "cosmossdk.io/core/appmodule" 11 "cosmossdk.io/log" 12 storetypes "cosmossdk.io/store/types" 13 14 addresscodec "github.com/cosmos/cosmos-sdk/codec/address" 15 "github.com/cosmos/cosmos-sdk/runtime" 16 "github.com/cosmos/cosmos-sdk/testutil/integration" 17 sdk "github.com/cosmos/cosmos-sdk/types" 18 moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" 19 "github.com/cosmos/cosmos-sdk/x/auth" 20 authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" 21 authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" 22 authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 23 "github.com/cosmos/cosmos-sdk/x/mint" 24 mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" 25 minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" 26 ) 27 28 // Example shows how to use the integration test framework to test the integration of SDK modules. 29 // Panics are used in this example, but in a real test case, you should use the testing.T object and assertions. 30 func Example() { 31 // in this example we are testing the integration of the following modules: 32 // - mint, which directly depends on auth, bank and staking 33 encodingCfg := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, mint.AppModuleBasic{}) 34 keys := storetypes.NewKVStoreKeys(authtypes.StoreKey, minttypes.StoreKey) 35 authority := authtypes.NewModuleAddress("gov").String() 36 37 // replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t)) 38 logger := log.NewNopLogger() 39 40 cms := integration.CreateMultiStore(keys, logger) 41 newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger) 42 43 accountKeeper := authkeeper.NewAccountKeeper( 44 encodingCfg.Codec, 45 runtime.NewKVStoreService(keys[authtypes.StoreKey]), 46 authtypes.ProtoBaseAccount, 47 map[string][]string{minttypes.ModuleName: {authtypes.Minter}}, 48 addresscodec.NewBech32Codec("cosmos"), 49 "cosmos", 50 authority, 51 ) 52 53 // subspace is nil because we don't test params (which is legacy anyway) 54 authModule := auth.NewAppModule(encodingCfg.Codec, accountKeeper, authsims.RandomGenesisAccounts, nil) 55 56 // here bankkeeper and staking keeper is nil because we are not testing them 57 // subspace is nil because we don't test params (which is legacy anyway) 58 mintKeeper := mintkeeper.NewKeeper(encodingCfg.Codec, runtime.NewKVStoreService(keys[minttypes.StoreKey]), nil, accountKeeper, nil, authtypes.FeeCollectorName, authority) 59 mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper, nil, nil) 60 61 // create the application and register all the modules from the previous step 62 integrationApp := integration.NewIntegrationApp( 63 newCtx, 64 logger, 65 keys, 66 encodingCfg.Codec, 67 map[string]appmodule.AppModule{ 68 authtypes.ModuleName: authModule, 69 minttypes.ModuleName: mintModule, 70 }, 71 ) 72 73 // register the message and query servers 74 authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(accountKeeper)) 75 minttypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), mintkeeper.NewMsgServerImpl(mintKeeper)) 76 minttypes.RegisterQueryServer(integrationApp.QueryHelper(), mintkeeper.NewQueryServerImpl(mintKeeper)) 77 78 params := minttypes.DefaultParams() 79 params.BlocksPerYear = 10000 80 81 // now we can use the application to test a mint message 82 result, err := integrationApp.RunMsg(&minttypes.MsgUpdateParams{ 83 Authority: authority, 84 Params: params, 85 }) 86 if err != nil { 87 panic(err) 88 } 89 90 // in this example the result is an empty response, a nil check is enough 91 // in other cases, it is recommended to check the result value. 92 if result == nil { 93 panic(fmt.Errorf("unexpected nil result")) 94 } 95 96 // we now check the result 97 resp := minttypes.MsgUpdateParamsResponse{} 98 err = encodingCfg.Codec.Unmarshal(result.Value, &resp) 99 if err != nil { 100 panic(err) 101 } 102 103 sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) 104 105 // we should also check the state of the application 106 got, err := mintKeeper.Params.Get(sdkCtx) 107 if err != nil { 108 panic(err) 109 } 110 111 if diff := cmp.Diff(got, params); diff != "" { 112 panic(diff) 113 } 114 fmt.Println(got.BlocksPerYear) 115 // Output: 10000 116 } 117 118 // ExampleOneModule shows how to use the integration test framework to test the integration of a single module. 119 // That module has no dependency on other modules. 120 func Example_oneModule() { 121 // in this example we are testing the integration of the auth module: 122 encodingCfg := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}) 123 keys := storetypes.NewKVStoreKeys(authtypes.StoreKey) 124 authority := authtypes.NewModuleAddress("gov").String() 125 126 // replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t)) 127 logger := log.NewLogger(io.Discard) 128 129 cms := integration.CreateMultiStore(keys, logger) 130 newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger) 131 132 accountKeeper := authkeeper.NewAccountKeeper( 133 encodingCfg.Codec, 134 runtime.NewKVStoreService(keys[authtypes.StoreKey]), 135 authtypes.ProtoBaseAccount, 136 map[string][]string{minttypes.ModuleName: {authtypes.Minter}}, 137 addresscodec.NewBech32Codec("cosmos"), 138 "cosmos", 139 authority, 140 ) 141 142 // subspace is nil because we don't test params (which is legacy anyway) 143 authModule := auth.NewAppModule(encodingCfg.Codec, accountKeeper, authsims.RandomGenesisAccounts, nil) 144 145 // create the application and register all the modules from the previous step 146 integrationApp := integration.NewIntegrationApp( 147 newCtx, 148 logger, 149 keys, 150 encodingCfg.Codec, 151 map[string]appmodule.AppModule{ 152 authtypes.ModuleName: authModule, 153 }, 154 ) 155 156 // register the message and query servers 157 authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(accountKeeper)) 158 159 params := authtypes.DefaultParams() 160 params.MaxMemoCharacters = 1000 161 162 // now we can use the application to test a mint message 163 result, err := integrationApp.RunMsg(&authtypes.MsgUpdateParams{ 164 Authority: authority, 165 Params: params, 166 }, 167 // this allows to the begin and end blocker of the module before and after the message 168 integration.WithAutomaticFinalizeBlock(), 169 // this allows to commit the state after the message 170 integration.WithAutomaticCommit(), 171 ) 172 if err != nil { 173 panic(err) 174 } 175 176 // verify that the begin and end blocker were called 177 // NOTE: in this example, we are testing auth, which doesn't have any begin or end blocker 178 // so verifying the block height is enough 179 if integrationApp.LastBlockHeight() != 2 { 180 panic(fmt.Errorf("expected block height to be 2, got %d", integrationApp.LastBlockHeight())) 181 } 182 183 // in this example the result is an empty response, a nil check is enough 184 // in other cases, it is recommended to check the result value. 185 if result == nil { 186 panic(fmt.Errorf("unexpected nil result")) 187 } 188 189 // we now check the result 190 resp := authtypes.MsgUpdateParamsResponse{} 191 err = encodingCfg.Codec.Unmarshal(result.Value, &resp) 192 if err != nil { 193 panic(err) 194 } 195 196 sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) 197 198 // we should also check the state of the application 199 got := accountKeeper.GetParams(sdkCtx) 200 if diff := cmp.Diff(got, params); diff != "" { 201 panic(diff) 202 } 203 fmt.Println(got.MaxMemoCharacters) 204 // Output: 1000 205 }