简体   繁体   中英

Testing models and services with Laravel, PHPSpec and PHPUnit

Im having difficulty deciding or understanding the best approach to testing in Laravel.

I really like the behavioural side of PHPSpec testing, although it is just not compatible with testing Eloquent models or anything related to an active record ORM.

When testing things like service providers PHPSpec seems like the way to go.

** Is it desirable to test models with something like PHPUnit, then test other non ORM layers such as service providers with something like PHPSpec? ***

I don't know Laravel, but reading problems people have with unit testing it tells me there's a lot of design issues in there. I understood that those problematic features of Laravel are optional, so there's hope!

See my comparision of PhpSpec vs PhpUnit in an answer of another question: First Shot at Testing Laravel 4 apps (PHPSpec/BDD vs. PHPUnit/TDD)

I'm guessing you'll face lots of problems using PhpSpec with Laravel, and often you'll have to avoid specing Laravel specific quirks, or avoiding them (facades are optional, you can use proper dependency injection). I'd aim on having as much code as possible independent from the framework and properly unit test them. Then, you can have a thin layer of framework glue code, covered with functional or integration tests. Apply the dependency injection.

As an example taken from the land of Symfony and Doctrine, I usually don't write specs for Doctrine repositories. Well, I only expect they implement a certain interface. That's all. The rest is covered with my acceptance tests. There is no much value in verifying that repositories use query builder to produce an expected query. No point really.

Going back to the tools, I can see myself mixing different kind of testing tools for different kinds of testing:

  • phpspec - unit tests - I'll write most of the tests on this level
  • behat - acceptance tests
  • phpunit - integration and functional tests - I'll have a small number of these, as they're fragile and slow.

This really has little to do with Laravel specifically and is actually a fundamental problem with ActiveRecord as a pattern. When you use ActiveRecord you sacrifice testability. ActiveRecord is irreconcilably linked to database persistence.

If you are looking to use a test-first approach I recommend using a different approach to persistence. Write your objects to function together. Then attach persistence later with something like Doctrine.

If you want to use ActiveRecord anyway, then you're going to need to do things a bit different. Laravel doesn't force the use of Eloquent. But, it does ship with it out of the box. ActiveRecord is a tool that's more or less appropriate for writing CRUD applications. If you're doing something more complicated, I would suggest Doctrine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM