'How to test system that requires Time resource?

I want to write tests for system that moves entities and detects collisions, system uses Res<Time> to ensure that entities move with constant speed. I was trying to write test following this example, but it doesn't use Time. My test creates world and inserts two entities and tries to run my system.

let mut world = World::default();

/*  here insert entities into world */

let mut update_stage = SystemStage::parallel();
update_stage.add_system(move_system);

It doesn't insert Time resource so unsurprisingly running it ends with

panicked at 'Resource requested by io_project::move_system::move_system does not exist: bevy_core::time::time::Time'

World has method insert_resource() but I wasn't able to figure out if I can use it to insert Time resource.

I was also wondering if it would be possible to use some kind of ''fake'' time, meaning that instead of checking how much time really passed I would call something like time.pass_seconds(1.). This would be useful to simulate very high or low framerate and create more consistent results.

I am using bevy 0.6.1



Solution 1:[1]

In the source code (https://github.com/bevyengine/bevy/blob/main/crates/bevy_core/src/time/time.rs) there's an example which covers adding the Time resource for tests, as well as simulating time passing.

I've included it below for quick reference:

# use bevy_core::prelude::*;
# use bevy_ecs::prelude::*;
# use bevy_utils::Duration;
# fn main () {
#     test_health_system();
# }

struct Health {
     // Health value between 0.0 and 1.0
     health_value: f32,
}
    
fn health_system(time: Res<Time>, mut health: ResMut<Health>) {
// Increase health value by 0.1 per second, independent of frame rate, but not beyond 1.0
     health.health_value = (health.health_value + 0.1 * time.delta_seconds()).min(1.0);
}
    
// Mock time in tests
fn test_health_system() {
     let mut world = World::default();
     let mut time = Time::default();
     time.update();
     world.insert_resource(time);
     world.insert_resource(Health { health_value: 0.2 });
    
     let mut update_stage = SystemStage::single_threaded();
     update_stage.add_system(health_system);
    
     // Simulate that 30 ms have passed
     let mut time = world.resource_mut::<Time>();
     let last_update = time.last_update().unwrap();
     time.update_with_instant(last_update + Duration::from_millis(30));
    
     // Run system
     update_stage.run(&mut world);
    
     // Check that 0.003 has been added to the health value
     let expected_health_value = 0.2 + 0.1 * 0.03;
     let actual_health_value = world.resource::<Health>().health_value;
     assert_eq!(expected_health_value, actual_health_value);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1