Names of traits that enable mocks

⚓ Rust    📅 2026-06-25    👤 surdeus    👁️ 2      

surdeus

I can distinguish two types of trait, at least for the purpose of naming them in the application I'm developing.

  • A role-named trait is named for what it does and may have several implementors. For example, trait Printable might have a function print() that is implemented by diverse structs such Invitation and Order. struct PrintScheduler has something like pub fn queue(&mut self, to_be_printed: Arc<Mutex<dyn Printable>>) to queue things to to be printed in due course.
  • A service interface trait abstracts a single concrete struct so it can be injected and mocked. I've not yet been able to find a Rust-idiomatic way to name such traits. So let's explore one of many real examples from my application.

Tuner is a struct that receives microtuning specifications in a given format, and converts each microtuning into a set of MIDI messages that are then sent to a synthesizer of a particular range of models. From the MIDI messages, the synthesizer's firmware configures its tuning to conform with the required microtuning. To facilitate testing, actually sending the MIDI messages is decoupled from Tuner . We need:

  • a struct that can actually send MIDI messages (the production struct);
  • a struct that sends no MIDI messages but allows tests to confirm that Tuner will send them correctly (the mock struct);
  • a trait that allows either struct to be injected into Tuner .

What would you call the two MIDI sender structs and their common trait? The mock struct is the easy one: MockMidiSender. But what about the the production struct and the trait? There are several options.

  • trait MidiSender with something like struct MidiSenderImpl or struct RealMidiSender. Yet, as the production struct is what actually sends MIDI, we should not have to qualify its name. And I understand that Rust naming guidelines discourage Impl suffixes for structs.
  • struct MidiSender with something like trait MidiSenderTrait or trait MidiSenderBase. It's a trait, so it should not need a Trait suffix. And Base sounds like a superclass in object-oriented programming languages, which it not what is going on here.
  • struct MidiSender with trait TMidiSender. I like that. However, T in Rust is a common type parameter, so perhaps it would be better to avoid it in this context.
  • struct MidiSender with trait IMidiSender, where I stands for interface and is the standard prefix for interface names, where interface is the equivalent of trait in .NET. This is what I've chosen as the standard for service interface traits in my application. But many Rust developers will understandably not like borrowing from a rather different development technology. I'm an experienced C#/.NET developer and am quite new to Rust.

What would you do?

2 posts - 2 participants

Read full topic

🏷️ Rust_feed