When you're testing the third-party component's failure modes, the tests you're writing are functional tests belonging to the nontrivial gateway implementation (e.g. ODBCDataStoreGateway).
The important thing about the gateway interface is that it's an error boundary: you don't need to think about "server errors" when dealing with a DataStoreGateway; DataStoreGateways don't have server errors. The ODBC object the ODBCDataStoreGateway holds might hand it a server error, but it won't propagate that back to you. It'll just put out a plain† DataStoreGateway::InsertError or somesuch.
† The exception should probably hold a copy of the implementation-exception that triggered it, but this is just for the sake of debugging the implementation. The client should never unwrap the internal exception.
> you don't need to think about "server errors" when dealing with a DataStoreGateway; DataStoreGateways don't have server errors.
I'm not sure why you even make that distinction. More than once I've dealt with servers that occasionally time out and fail; (say once a week or so). I wish to test what I show on my UI under those conditions, and what part of the text and status codes returned from the remote server that represent (or whatever) its failure I will choose to display.
Doing so without using a mock seems pointlessly obtuse and roundabout when I can make a mock to insert whatever error response I want at any interesting point in my code.
2. Your client has a network connectivity problem.
I've never seen a client who needs to know #1. All they care about is that there was a DataStoreGateway::TransientInsertError, and that TransientInsertErrors mean retrying and notifying the UI that their work hasn't been committed yet.
#2 isn't a problem the DataStoreGateway should be responsible for, because it will affect almost everything in the system in one way or another, and you don't want to have to write that code repeatedly. It's more likely a kind of Alarm--the kind of thing that gets pushed out from wherever it is to a global alarm handler, which then does something like putting the UI into a different root view-controller state, e.g. darkening it and covering it with a modal saying "lost connection."
The important thing about the gateway interface is that it's an error boundary: you don't need to think about "server errors" when dealing with a DataStoreGateway; DataStoreGateways don't have server errors. The ODBC object the ODBCDataStoreGateway holds might hand it a server error, but it won't propagate that back to you. It'll just put out a plain† DataStoreGateway::InsertError or somesuch.
† The exception should probably hold a copy of the implementation-exception that triggered it, but this is just for the sake of debugging the implementation. The client should never unwrap the internal exception.