PHPUnit builds both with the same method, which is why the distinction gets lost. A stub exists to let the test proceed — it returns a value. A mock exists to assert that a call happened, with particular arguments, a particular number of times.
// stub: the gateway just needs to answer
$gateway = $this->createMock(Gateway::class);
$gateway->method('charge')->willReturn(new Receipt('ok'));
// mock: the assertion IS that charge was called once, with this amount
$gateway = $this->createMock(Gateway::class);
$gateway->expects($this->once())
->method('charge')
->with($this->equalTo(4900));
expects() is the line that turns one into the other. Over-using mocks produces tests that assert how the code is written rather than what it does, so they fail on every refactor while catching nothing. Mock at the edges — the payment gateway, the mailer — and stub everything in between.