For smaller projects I definitely agree with having both unit and integration tests, especially for libraries. One thing to look out for is the fact that you can always "cheat" in unit tests, e.g. you can be "lazy" and set up some internal state directly in the test to skip huge amounts of initialization, this of course becomes a problem when there's no actual integration test for making sure that the exact state can also be triggered from the outside when using the API. In my experience, ensuring that these cases are always covered can become pretty complicated once the project grows.
In our special case we have about 100 different endpoints all versioned and all dependent on multiple endpoints from the (rather badly documented) APIs of our customer. Most of the work our API does is spent combining / enriching the customers data and performing integration across the subresources. Setting up individual mocks for every single on of these complex requests flows manually is pretty much impossible at this scale.
So doing black box testing and enforcing a 100% test coverage (best for avoiding dead code) helps keeping us sane. In the end we don't care so much about how the implementation behind our HTTP response looks as long as we return the correct data in the end. The code itself still has to look good though :)
yeah, well you just test what you own anyway, for other stuff you could just grab some kind of dummy response and use that for testing your manipulation of that data, but of course you have to trust your customers endpoints to return the data in the correct format because that is out of your control.
We've always found that writing your own smoke tests for the other guy's code saves a lot of head scratching and the game I like to call Blame Tennis, when each side insists that any new problem must be in the other side's stuff because surely WE haven't broken anything.
These have become known in Pivotal as "frenemy tests". Poke a remote API to see that a) it is running b) it hasn't dropped a world-stopping change.
Typically run as a pre-build sanity check when you have remote integrations.
On some Labs projects we've written extensive request tests and stub services based on documentation, then handed those to the upstream service. Usually there is some angst at this point, being the first time that any kind of TDD suite has turned up to ask awkward questions.
I still maintain F5 owes me a job. I did QA for them for a year back in the dot-com boom. The first couple of versions of BigIP didn't really support session affinity, despite being the flagship feature. I think we filed something like 6-8 pretty big bugs, all in different parts of the code.
Sadly, despite not working, they were still about 4 years ahead of their competitors.
In our special case we have about 100 different endpoints all versioned and all dependent on multiple endpoints from the (rather badly documented) APIs of our customer. Most of the work our API does is spent combining / enriching the customers data and performing integration across the subresources. Setting up individual mocks for every single on of these complex requests flows manually is pretty much impossible at this scale.
So doing black box testing and enforcing a 100% test coverage (best for avoiding dead code) helps keeping us sane. In the end we don't care so much about how the implementation behind our HTTP response looks as long as we return the correct data in the end. The code itself still has to look good though :)