Make DockerClient more test-friendly

Attempting to use DockerClient with unit-tested code is a bit of a challenge:

  • You can mock or stub it, but with the new Cmd objects it returns, you have to mock or stub those objects as well (or use deep stubs). This leads to a whole lot of boilerplate and very brittle tests.
  • There's no way to inject mocks for the Cmd objects since it creates new instances of them directly.

What I propose (and feel free to suggest something else) is a CommandFactory interface that is passed into DockerClient at construction, which it then uses to create the commands rather than directly calling new SomeCmd(). A provided default implementation of the factory would basically do just what DockerClient does now. This would maintain backwards compatibility with the current API and provide a better means of injecting mocks (or spies) for specific commands.

An API-breaking change would be to move the Command creation responsibility out of DockerClient entirely and into the CommandFactory. Then, DockerClient's single responsibility would be to set the baseResource and authConfig on commands and execute them (essentially, the execute method). This would also suggest that the exec method on commands should not be exposed.

Thoughts?