Tests that only test one thing are more informative than tests where failure can come from many sources. How can you isolate your tests from external influences? Simply put, replace the expensive, messy, unreliable, slow, complicated resources with stubs made from plain Java objects. For example, you can implement what is in reality a complicated computation by returning a constant, at least for the purposes of a single test.
A problem solved by stubs is the allocation of expensive external resources. If every test has to connect to a database, the tests are slow. If, instead, your design allows you to replace the real database with a stub database, you can write tests that are fast. With a bit more cleverness, you can create an option for running the tests with the real database or the stub database so you can use your tests for both local development or integration testing.
What is lost when stubbing? If the stub doesn't faithfully reproduce the behavior of the real object, you run the risk of having your tests pass but having the real system fail. Also, if you need the option to use a real or a stub object, you will have to pass the correct object to use as a parameter, often in a constructor, rather than rely on global variables. Overall, though, this results in a cleaner design.
Consider a program that has to send email. We could test it by actually sending email and then running an email client a few seconds later to fetch the email and check the message's contents. However, ...