The principle is abstract until you write the test. If exercising one method means stubbing five others that the code under test never calls, the interface is doing more than one job and the test is telling you so.
// the test needs all of it to use any of it
interface Storage
{
public function read(string $k);
public function write(string $k, $v);
public function delete(string $k);
public function flush();
public function stats(): array;
}
interface Reader { public function read(string $k); }
interface Writer { public function write(string $k, $v); }
Splitting by client rather than by implementation is the part to get right: the interfaces should reflect what callers need, not how the storage is built. One class can implement several. The immediate payoff is smaller mocks; the longer one is that a component declaring Reader in its constructor cannot quietly start writing.