Otherwise your test implicitly make assumptions like “User A is always off-line” (or bucket A is always empty), add a reader of the test would have to go find where that assumption is hardcoded in the simulator and verify it separately from the test itself.
To someone reading that test it is not intuitive that user A is always off-line or bucket A is empty.
If you mock out in line, you can have tests that mock user a / bucket a — to simulate any state for any user or bucket. Perhaps multiple states in one test.
Also think about scenarios like the bucket is initially populated, but then on a subsequent request, it’s empty.
With the simulator approach, you’d have an endless number of permutations of scenarios to add — each of these scenarios would be highly coupled to the test it belongs to, so why not just put it in line in the test itself?
Any reader of the test that uses inline mocking would clearly see which scenario is being tested instead of having to dive into a separate simulator to see what special treatment is hardcoded for User a / bucket a (or maintaining potentially hundreds or thousands of simulated buckets with ad hoc names like “empty-on-second-request” or “bucket–that-responds-slow-and-times-out-but-succeeds-on-retry”.