Reputation: 312
Our code is heavily using Mocktopus
but we're planning to use the rust stable now.
This is a scenario that I can't resolve:
use mocktopus::*;
use mocktopus::mocking::{Mockable, MockResult};
use crate::prod::Limiter;
pub mod helper {
#[cfg(test)]
use mocktopus::macros::mockable;
#[cfg_attr(test, mockable)]
pub fn min() -> u64 {
0
}
#[cfg_attr(test, mockable)]
pub fn max() -> u64 {
10
}
pub fn one() -> u64 {
1
}
}
pub mod prod {
pub struct Limiter{
min: u64,
max: u64
}
impl Limiter {
pub fn new() -> Self {
Limiter {
min: 0,
max: 0,
}
}
pub fn set_min(&mut self, allow_zero:bool){
self.min = if allow_zero {
super::helper::min()
} else { super::helper::one() };
}
pub fn set_max(&mut self,allow_max_of_type:bool) {
self.max = if allow_max_of_type {
u64::MAX
} else { super::helper::max() };
}
pub fn get_min(&self) -> u64 {
self.min
}
pub fn get_max(&self) -> u64 {
self.max
}
}
}
(note: this is NOT the actual code; just a VERY simple view of what our code structure looks like)
For Mocktopus
I can test Limiter like so:
#[test]
fn test_get_min() {
let mut limiter = Limiter::new();
helper::min.mock_safe(|| MockResult::Return(2));
limiter.set_min(true);
assert_eq!(limiter.get_min(), 2);
}
But I can't find any libraries similar to this.
I tried mockall
, but it requires me to wrap the structure inside mock!
macro.
For context: I can't simply do that, since the structure (the Limiter
) is created through another macro.
Here's a project(Interlay which uses Parity's substrate) that showcases better my dilemma:
To test register_vault()
method:
pub fn register_vault(
origin: OriginFor<T>,
currency_pair: DefaultVaultCurrencyPair<T>,
#[pallet::compact] collateral: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
...
Self::_register_vault(vault_id, collateral)?;
...
}
where _register_vault()
calls the get_minimum_collateral_vault()
function:
pub fn _register_vault(vault_id: DefaultVaultId<T>, collateral: BalanceOf<T>) -> DispatchResult {
...
ensure!(amount.ge(&Self::get_minimum_collateral_vault(collateral_currency))?,
Error::<T>::InsufficientVaultCollateralAmount);
...
}
The function get_minimum_collateral_vault
is set to mockable:
#[cfg_attr(test, mockable)]
impl<T: Config> Pallet<T> {
...
fn get_minimum_collateral_vault(currency_id: CurrencyId<T>) -> Amount<T> {
let amount = MinimumCollateralVault::<T>::get(currency_id);
Amount::new(amount, currency_id)
}
}
Inside this test case mocks the function get_minimum_collateral_vault
to be able to test register_vault
:
VaultRegistry::get_minimum_collateral_vault
.mock_safe(move |currency_id| MockResult::Return(Amount::new(200, currency_id)));
...
let result = VaultRegistry::register_vault(origin, id.currencies.clone(), collateral);
assert_err!(result, TestError::InsufficientVaultCollateralAmount);
Upvotes: 0
Views: 87