brendanhay / amazonka

A comprehensive Amazon Web Services SDK for Haskell.
https://amazonka.brendanhay.nz
Other
604 stars 228 forks source link

S3 PutObject and GetObjectResponse are coupled to IO #524

Open aztecrex opened 5 years ago

aztecrex commented 5 years ago

The IO coupling of PutObject and GetObjectResponse make testing difficult.

When testing code that uses Amazonka, it is effective to use test doubles that set up AWS request/response scenarios purely with no IO. This does not work for S3 because PutObject and Rs GetObject have IO in their definitions. The can't be Eq for example; and checking that bodies are supplied/consumed correctly requires setting up consumers and producers in IO. It also means the operations under test must themselves depend on IO rather than abstractions that are ultimately implemented in IO but can be kept pure for testing.

Is it possible to use a non-specific monad rather than IO in the definitions of these types?

nhibberd commented 5 years ago

I assume you are referring to the RsBody in the response?

nhibberd commented 5 years ago

From my experience most people testing interactions around amazonka test directly against aws and/or create abstractions on top of there uses of amazonka to swap out amazonka for another interrupter (eg something non IO)

aztecrex commented 5 years ago

RsBody in response and RqBody in request, yes.

We, of course, create abstractions that are fulfilled by implementations in Amazonka. All of our application code is tested against those abstractions (e.g. generalized object store) without any knowledge of AWS whatsoever.

However, to complete the walk down to the "simple passthrough" level required by transitive testing, we need to test that our implementations of those abstractions via Amazonka are correct. e.g. the happy path that retrieves an object or the sad path where something goes wrong while streaming the body. With the current coupling to IO in Amazonka S3, I can't see a way to test those cases purely without jumping through a bunch of hoops. It also pollutes our implementations with IO, disallowing us to express the implementations in a pure Amazonka abstraction for S3.

We're not going to operate AWS itself during unit test runs. The funny thing is that the Amazonka architecture supports our testing pattern for nearly every service--which is why we use it so extensively. It's just that the S3 declarations assume a network streaming protocol in IO instead of a streaming abstraction, and that causes the problems. We work around it, but it breaks the patterns we've established with all the other AWS services.

I suspect I'm a lone voice here :)