java - I want to mock a proprietary class that extends InputStream, mock read, verify close -
i want use mockito mock amazons3 , test opening stream , verifying stream closed after code has read it. i'd bytes read stream. this:
amazons3 client = mock(amazons3.class); when(tm.getamazons3client()).thenreturn(client); s3object response = mock(s3object.class); when(client.getobject(any(getobjectrequest.class))).thenreturn(response); s3objectinputstream stream = mock(s3objectinputstream.class); when(response.getobjectcontent()).thenreturn(stream); somehow mock read method myobject me = new myobject(client); byte[] bra me.getbytes(file f, offset, length); assertequals(length, bra.length); verify(stream).close();
you work in simple way:
when(stream.read()).thenreturn(0, 1, 2, 3 /* ... */);
that said, right now, you're mocking amazon's implementation. means if of methods turn final, you'll in bad shape, because mockito doesn't support mocking final methods due compiler constraints. mocking types don't own tempting, can lead breakage.
if goal test getbytes
returns right value , closes stream, more stable approach may refactor use arbitrary inputstream:
class myobject { public byte[] getbytes(file f, int offset, int length) { /* ... */ // delegate actual call getbytes method. return getbytes(s3objectinputstream, f, offset, length); } /** call package-private delegate in tests arbitrary stream. */ static byte[] getbytes(inputstream s, file f, int offset, int length) { /* ... */ } }
at point, can test using spy(new bytearrayinputstream(your_byte_array))
, compelling test—complete call verify(stream).close()
.
along lines, solution add seam can control, wrapping getbytes
afar:
class myobject { public byte[] getbytes(file f, int offset, int length) { /* ... */ inputstream inputstream = getstream(response.getobjectcontent()); /* ... */ } /** default, pass in stream have. */ inputstream getstream(s3objectinputstream s3stream) { return s3stream; } } class myobjecttest { @test public void yourtest() { /* ... */ myobject myobject = new myobject(client) { /** instead of returning s3 stream, insert own. */ @override inputstream getstream() { return yourmockstream; } } /* ... */ } }
remember, though, you're testing way think amazon s3 should work, not whether continues work in practice. if goal "test opening stream [s3]", integration test runs against actual s3 instance idea, cover gap between s3 mock , s3 in reality.
Comments
Post a Comment