Once you expose a class as virtual or abstract, that means that you can extend it. There's two basic camps out there, those that think that things should be final by default, and those that don't. One logical argument I found has this to say:
Well, a non-final class can be extended of course! Any public or protected methods can be overridden and protected fields read/written. More importantly, you cannot reverse the decision — i.e. once a public non-final class, always a public non-final class. In contrast, when using final as the default for classes, you can reverse your decision — i.e. you can always open, but you can never close.
Do some research, you'll find more arguments like this. If a class is final by default, you can assure yourself it's not being used anywhere else--and most classes never will be. In contrast, once you open it up for subclassing, you have introduced a new layer of complexity for that class for all time (it's now open). The page above also says:
Josh Bloch in his (also excellent) book Effective Java states “you should make each class or member as inaccessible as possible”.
Apex Code makes this easy for developers. I've written thousands of Apex Code classes, and I can likely count the number of times that I've needed non-final classes on both hands. They're actually really super-rare to see in practice, so it should be the default model (and thus, it is!).
You can think of virtual/abstract as "more permissive" than final, because you can poke in to it. However, as far as testing goes, we have the Stub API for mocking objects, and we have @TestVisible Annotation for reaching into an object only during testing. Between these two features, it's almost never necessary (if ever) to have your classes virtual by default just for test dependency injection. It makes all your code easier to read and maintain.