Simulación
Los mocks se usan en pruebas para excluir funcionalidades que no se quieren probar. Los mocks se usan cuando es difícil probar contra un componente externo.
El Soroban Rust SDK facilita probar contra un contrato real tanto como probar contra un mock de un contrato. En algunos ecosistemas se evitan las pruebas de integración. No ocurre así en el ecosistema Stellar. Consulta Pruebas de Integración.
Cómo escribir pruebas con mocks
El siguiente es un ejemplo de una prueba que usa un mock, escrita para probar el contrato increment-with-pause. El contrato tiene una función increment
que aumenta un contador en uno cada vez que se invoca. El contrato depende de otro contrato que controla si la función de incremento está en pausa.
Las siguientes pruebas configuran el contrato increment-with-pause
junto con un mock del contrato de pausa, e invocan varias veces la función del contrato de incremento bajo diferentes condiciones esperadas del contrato de pausa.
La siguiente prueba verifica que cuando el contrato de pausa no está en pausa, el contrato de incremento funciona.
#![cfg(test)]
use crate::{Error, IncrementContract, IncrementContractArgs, IncrementContractClient, Pause};
use soroban_sdk::{contract, contractimpl, Env};
mod notpaused {
use super::*;
#[contract]
pub struct Mock;
#[contractimpl]
impl Pause for Mock {
fn paused(_env: Env) -> bool {
false
}
}
}
#[test]
fn test_notpaused() {
let env = Env::default();
let pause_id = env.register(notpaused::Mock, ());
let contract_id = env.register(
IncrementContract,
IncrementContractArgs::__constructor(&pause_id),
);
let client = IncrementContractClient::new(&env, &contract_id);
assert_eq!(client.increment(), 1);
assert_eq!(client.increment(), 2);
assert_eq!(client.increment(), 3);
}
La siguiente prueba verifica que cuando el contrato de pausa está en pausa, la función del contrato de incremento rechaza los intentos de incrementar.
#![cfg(test)]
use crate::{Error, IncrementContract, IncrementContractArgs, IncrementContractClient, Pause};
use soroban_sdk::{contract, contractimpl, Env};
mod paused {
use super::*;
#[contract]
pub struct Mock;
#[contractimpl]
impl Pause for Mock {
fn paused(_env: Env) -> bool {
true
}
}
}
#[test]
fn test_paused() {
let env = Env::default();
let pause_id = env.register(paused::Mock, ());
let contract_id = env.register(
IncrementContract,
IncrementContractArgs::__constructor(&pause_id),
);
let client = IncrementContractClient::new(&env, &contract_id);
assert_eq!(client.try_increment(), Err(Ok(Error::Paused)));
}
La mayoría de las pruebas, ya sean unitarias, con mocks o de integración, serán muy similares a estas. Harán cuatro cosas:
- Crear un ambiente, el
Env
. - Registrar el/los contratos que se van a probar.
- Invocar funciones usando el cliente generado.
- Verificar el resultado.
La simulación introduce supuestos sobre el comportamiento de otro contrato. Aunque el contrato publique una interfaz que diga que devolverá un bool (true/false), los contratos pueden devolver cualquier tipo.
impl Pause {
fn paused(env: Env) -> ? { ? }
}
Esta es una razón por la que es útil probar y hacer fuzzing usando dependencias reales y programar con defensiva asumiendo que cualquier llamada externa puede causar que tu contrato falle.
Consulta Pruebas de Integración para saber cómo probar con dependencias reales.
El Soroban Rust SDK maneja las llamadas a contratos de forma defensiva para que cualquier error inesperado o tipo inesperado devuelto haga que la ejecución se detenga. El SDK también ofrece métodos para realizar estas llamadas y para interceptar situaciones de error. Consulta Realizar llamadas entre contratos para más detalles.
Guías en esta categoría:
📄️ Pruebas Unitarias
Las pruebas unitarias son pruebas pequeñas que prueban contratos inteligentes.
📄️ Simulación
Simulación de contratos dependientes en pruebas.
📄️ Prueba de Autorización
Escribe pruebas que verifiquen la autorización del contrato.
📄️ Eventos de Prueba
Escribe pruebas que verifiquen los eventos de contrato.
📄️ Pruebas de Integración
Las pruebas de integración utilizan contratos de dependencia en lugar de simulaciones.
📄️ Pruebas de Fork
Pruebas de integración utilizando datos de mainnet.
📄️ Fuzzing
Fuzzing y pruebas de propiedades para encontrar comportamientos inesperados.
📄️ Pruebas Diferenciales
Las pruebas diferenciales detectan cambios no intencionados.
📄️ Pruebas Diferenciales con Imágenes de Prueba
Prueba diferencial utilizando imágenes de prueba automáticas.
📄️ Pruebas de Mutación
La prueba de mutación encuentra código no probado.
📄️ Cobertura de Código
Las herramientas de cobertura de código encuentran código no probado.