Ok, so I've tracked down where it changes the setting object it will update.
In the file core/model/modx/modprocessor.class.php, there's an abstract class:
abstract class modObjectUpdateProcessor extends modObjectProcessor
In the initialize method, it calls
$this->object = $this->modx->getObject($this->classKey,$primaryKey);
Before this line, $this->object references the correct setting object, after this call it's changed to the first instance of a user setting found in the database (for example, if I delete the test_id setting, leaving only 'another_id', then create a whole new setting, then any change to the new setting is made to 'another_id' instead). Commenting out this line results in the correct object being updated in the database.
It's a bit weird, one because why re-initialise the object if it already exists, and two the $primaryKey actually references the correct setting key but returns the wrong object.
The modObjectUpdateProcessor initialize method is called down the chain by the core/model/modx/processors/security/user/setting/update.class.php.