It was a cold day in this first month of this new decade, a cold day full of coding. I was building some facade API to help one of our teams improve the reach of their test framework. Messages pushed from a system to the other using Kafka and a bunch of other happy things. So there was that chunk of code I needed to implement which required retrieving objects stored in Amazon S3. Let me give you some context first. Let me tell you how I went and mocked S3Object.getObjectContent so that it provided me a mock to validate code processing an S3ObjectInputStream directly.
The codebase was inherited from people that thought it was a good idea to the frontend pushing files to the backend within a JSON payload. I don’t mean the occasional object, I mean files. Like images, pdfs and stuff. So, that codebase was supported by a test framework which while giving enough details about messages being pushed, didn’t provide any insight on these reaching subscribers. Our team after taking over the project went ahead and built tests to validate messages reach subscribers but not the contents. Contents being the JSON payload and files pushed to S3 to cater to Kafka’s 1MB message size limit.
Luckily for me, our team that replaced them did a stellar job at cleaning a whole lot of it. Another good thing is that I have carte blanche for that facade API. I decided to ditch a bunch of legacy stuff that while working seemed to do way more than I needed. Stripping intermediary libraries one after the other I ran into an issue. That facade API needed an endpoint that would return a file contents to the test framework from the S3 reference.
I chose to manipulate bytes directly since most of the files to handle are binaries, also that’s how they’re all stored. S3Object.getObjectContent is the right place to start. The method returns an S3ObjectInputStream. I could cheat by creating an instance of an S3Object and call setObjectContent to set up my test but we don’t do that here. Mocking is in the title, not lazily use readily available tools you can’t show off with. This post will end up shorter than usual as I’ll just share the implementation and the tests directly because there isn’t much to add to it.
The mocking part you came here for
Well, S3Object.getObjectContent returns an S3ObjectInputStream. Once you realize that S3ObjectInputStream is just a fancy InputStream, all you need is to write a mock for it. I guess you knew that bit, the other thing is that you need to override the read method you will use in your code. Here I opted to return the call on reading bytes from a StringInputStream using Mockito’s Answer. Since I pass a stream from a string, I can validate my function processes the bytes properly with a comparison at the end with that string’s bytes. Enjoy the free code!