In my experience, model testing has by far the highest payoff of bugs squashed per minute or line of test code written.
I hear some people saying their models are so simple they don't need tests. They're frequently surprised what issues later turn up, but in any case, if there's next-to-nothing in your models, it will take hardly any time to write full test coverage for them!
(Also, if your models are really simple that often means you've plonked your model code in the controllers, which aside from being bad practice in general makes it very different to test effectively, but we'll come back to that issue.)
For Rails model testing is covered by “unit tests” in Rails' built-in Test::Unit functionality, or by RSpec “model specs”.
(For programmers coming from other languages, “unit tests” here is misleading – usually unit tests are simply tests for a component of other kind. In the Rails Test::Unit world, unit tests refer specifically to model tests.)
Check out the previous article for more on Test::Unit and RSpec.
About that “SQL server doesn't barf” thing. There is a lot of noise at the moment about testing without hitting the DB, for speed. I agree, speed is very good and important since it means short iterations, and for most of your tests, you aren't interested in testing the repetitive DB CRUD operations, so bypassing is often worthwhile.
You can, for example, test out most calculators and state inquiries and so on with mocked attributes only.
But if you ever do any database stuff other than trivial CRUD, you must let the tests for at least those particular bits of code actually go to the DB.
I couldn't count the number of times I've seen problems with things like joins (especially scoped joins) and includes – for example, when someone's added an extra join or include and now there's two attributes in the select with the same name, so all the attribute names in the condition strings etc. need to be fully-qualified… All simple to fix, but they need to be tested for.
For any nontrivial model query or update statement, if you stub/mock out the database interaction, you're stubbing out the main thing that needs to be tested. 'Nuff said.
And anyone who thinks you can run against one database (eg. mysql or postgres) but test against something faster (eg. in-memory sqlite) needs their head examined.
Next in this series: