Saltar al contenido principal

Simulación

Los mocks se utilizan en las pruebas para excluir la funcionalidad que una prueba no quiere evaluar. Las simulaciones se utilizan cuando es difícil probar contra un componente externo.

consejo

El Soroban Rust SDK hace que sea igual de fácil realizar pruebas contra un contrato real que hacerlo contra un mock de un contrato. En algunos ecosistemas se evitan las pruebas de integración. No en el ecosistema Stellar. Consulta Pruebas de Integración.

Cómo Escribir Pruebas con Simulaciones

El siguiente es un ejemplo de una prueba que utiliza un mock, escrita para probar el [increment-with-pause contract]. El contrato tiene una función incrementar que aumenta el valor de un contador en uno en cada invocación. El contrato depende de otro contrato que controla si la funcionalidad de incremento está pausada.

Las siguientes pruebas configuran el contrato increment-with-pause, así como un contrato de pausa simulado, e invocan la función del contrato de incremento varias veces bajo diferentes condiciones en las que se espera que se encuentre el contrato de pausa.

La siguiente prueba verifica que cuando el contrato de pausa no está en pausa, las funciones del contrato de incremento funcionan.

#![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 comprueba 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 sea que estés escribiendo pruebas unitarias, simulaciones o pruebas de integración, se verán muy similares a estas pruebas. Harán cuatro cosas:

  1. Crear un entorno, el Env.
  2. Registrar el/los contrato(s) a probar.
  3. Invoca funciones utilizando el cliente generado.
  4. Afirma el resultado.
advertencia

La simulación introduce suposiciones sobre el comportamiento de otro contrato. Incluso si el contrato publica una interfaz que dice que devolverá un bool (verdadero/falso), los contratos pueden devolver cualquier tipo.

impl Pause {
fn paused(env: Env) -> ? { ? }
}

Esta es una razón por la que es útil probar y usar fuzzing con dependencias reales y programar de forma defensiva asumiendo que cualquier llamada a un contrato externo podría 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 manera defensiva para que cualquier error inesperado o tipo inesperado devuelto por el contrato llamado detenga la ejecución. El SDK también proporciona métodos para realizar estas llamadas y para interceptar situaciones de error. Consulta Hacer Llamadas Entre Contratos para más detalles.