|
| 1 | +# Keeper Testing |
| 2 | + |
| 3 | +The keeper package exposes an easy API for generating a set of "test keepers" and "test message |
| 4 | +servers" for performing integration testing on your application at the keeper level. Typical Cosmos |
| 5 | +SDK unit tests may use mocked keepers, or not use a full set that is representative of the full application. |
| 6 | + |
| 7 | +This setup allows developers to test all keepers in coordination without having to spin up a local network |
| 8 | +or full application. |
| 9 | + |
| 10 | +The framework initializes and returns keepers for the following modules: |
| 11 | +- `x/bank` |
| 12 | +- `x/auth` |
| 13 | +- `x/staking` |
| 14 | +- `x/distribution` |
| 15 | +- `x/feegrant` |
| 16 | +- `x/mint` |
| 17 | + |
| 18 | +and is easily extendable to add any other keepers that you may with to test upon setup. |
| 19 | + |
| 20 | +A typical testing flow that extends adds the Skip FeeMarket module might look like the following: |
| 21 | + |
| 22 | +```go |
| 23 | +import ( |
| 24 | + "testing" |
| 25 | + |
| 26 | + "github.com/cometbft/cometbft/libs/log" |
| 27 | + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" |
| 28 | + storetypes "github.com/cosmos/cosmos-sdk/store/types" |
| 29 | + sdk "github.com/cosmos/cosmos-sdk/types" |
| 30 | + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" |
| 31 | + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" |
| 32 | + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" |
| 33 | + testkeeper "github.com/skip-mev/chaintestutil/keeper" |
| 34 | + "github.com/stretchr/testify/require" |
| 35 | + |
| 36 | + feemarketkeeper "github.com/skip-mev/feemarket/x/feemarket/keeper" |
| 37 | + feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types" |
| 38 | +) |
| 39 | + |
| 40 | +// TestKeepers holds all keepers used during keeper tests for all modules |
| 41 | +type TestKeepers struct { |
| 42 | + testkeeper.TestKeepers |
| 43 | + FeeMarketKeeper *feemarketkeeper.Keeper |
| 44 | +} |
| 45 | + |
| 46 | +// TestMsgServers holds all message servers used during keeper tests for all modules |
| 47 | +type TestMsgServers struct { |
| 48 | + testkeeper.TestMsgServers |
| 49 | + FeeMarketMsgServer feemarkettypes.MsgServer |
| 50 | +} |
| 51 | + |
| 52 | +var additionalMaccPerms = map[string][]string{ |
| 53 | + feemarkettypes.ModuleName: nil, |
| 54 | + feemarkettypes.FeeCollectorName: {authtypes.Burner}, |
| 55 | +} |
| 56 | + |
| 57 | +// NewTestSetup returns initialized instances of all the keepers and message servers of the modules |
| 58 | +func NewTestSetup(t testing.TB, options ...testkeeper.SetupOption) (sdk.Context, TestKeepers, TestMsgServers) { |
| 59 | + options = append(options, testkeeper.WithAdditionalModuleAccounts(additionalMaccPerms)) |
| 60 | + |
| 61 | + _, tk, tms := testkeeper.NewTestSetup(t, options...) |
| 62 | + |
| 63 | + // initialize extra keeper |
| 64 | + feeMarketKeeper := FeeMarket(tk.Initializer, tk.AccountKeeper) |
| 65 | + require.NoError(t, tk.Initializer.LoadLatest()) |
| 66 | + |
| 67 | + // initialize msg servers |
| 68 | + feeMarketMsgSrv := feemarketkeeper.NewMsgServer(*feeMarketKeeper) |
| 69 | + |
| 70 | + ctx := sdk.NewContext(tk.Initializer.StateStore, tmproto.Header{ |
| 71 | + Time: testkeeper.ExampleTimestamp, |
| 72 | + Height: testkeeper.ExampleHeight, |
| 73 | + }, false, log.NewNopLogger()) |
| 74 | + |
| 75 | + err := feeMarketKeeper.SetState(ctx, feemarkettypes.DefaultState()) |
| 76 | + require.NoError(t, err) |
| 77 | + err = feeMarketKeeper.SetParams(ctx, feemarkettypes.DefaultParams()) |
| 78 | + require.NoError(t, err) |
| 79 | + |
| 80 | + testKeepers := TestKeepers{ |
| 81 | + TestKeepers: tk, |
| 82 | + FeeMarketKeeper: feeMarketKeeper, |
| 83 | + } |
| 84 | + |
| 85 | + testMsgServers := TestMsgServers{ |
| 86 | + TestMsgServers: tms, |
| 87 | + FeeMarketMsgServer: feeMarketMsgSrv, |
| 88 | + } |
| 89 | + |
| 90 | + return ctx, testKeepers, testMsgServers |
| 91 | +} |
| 92 | + |
| 93 | +// FeeMarket initializes the fee market module using the testkeepers intializer. |
| 94 | +func FeeMarket( |
| 95 | + initializer *testkeeper.Initializer, |
| 96 | + authKeeper authkeeper.AccountKeeper, |
| 97 | +) *feemarketkeeper.Keeper { |
| 98 | + storeKey := sdk.NewKVStoreKey(feemarkettypes.StoreKey) |
| 99 | + initializer.StateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, initializer.DB) |
| 100 | + |
| 101 | + return feemarketkeeper.NewKeeper( |
| 102 | + initializer.Codec, |
| 103 | + storeKey, |
| 104 | + authKeeper, |
| 105 | + authtypes.NewModuleAddress(govtypes.ModuleName).String(), |
| 106 | + ) |
| 107 | +} |
| 108 | +``` |
0 commit comments