I am writing some tests for an API. This particular API returns a BTreeMap object containing some data.
To test this I have written some code like this:
// part of a unit test
let total_volume = order_book.total_volume();
let mut expected_total_volume = BTreeMap::new();
expected_total_volume
.insert(
NotNan::new(100.0).unwrap(), NotNan::new(20.0).unwrap()
);
expected_total_volume
.insert(
NotNan::new(120.0).unwrap(), NotNan::new(10.0 + 12.0).unwrap()
);
assert_eq!(total_volume, expected_total_volume);
There is nothing wrong with this, but one could argue that expected_total_volume should not be mutable. It is an immutable object, the mutability is just there (and required) to construct it by progressively inserting each required data element.
Is there a way to build a BTreeMap like this such that the resulting value is immutable?
If this weren't the case, a completely general solution is creating and mutating the object in a smaller scope, by enclosing it in a block specific to the construction, then assigning the value of that block immutably to an outer binding.
Another completely general solution is to create an array/vec (for which literal syntax and a macro is available, respectively), then turn it into an iterator, and .collect() the iterator to the required type.
Note that the inability to take a &mut _ only applies to any given binding. So on the one hand, an alternative to collecting or the like is to just move the variable to a new binding:
let mut expected_total_volume = BTreeMap::new();
expected_total_volume.insert(..);
expected_total_volume.insert(..);
let expected_total_volume = expected_total_volume;
And on the other hand, be aware that the value is not "intrinsically immutable" or the like,[1] because further down one can always
let mut changed_my_mind = expected_total_volume;
changed_my_mind.insert(..);