Ложный метод чтения openInputStream - PullRequest
0 голосов
/ 11 сентября 2018

Я читаю порции данных из openInputStream и хотел имитировать его метод чтения.

 final byte[] testFileData = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a};

 CloudBlob cloudBlob = this.getCloudBlobContainer().getBlobReferenceFromServer(blobName);

    ByteArrayOutputStream blobStream = new ByteArrayOutputStream();

    try (final InputStream inputStream =  cloudBlob.openInputStream()) {

        //Read 4MB chunks of data 
        byte[] bufferToRead = new byte[4 * 1024 *1024];
        int bytesRead = inputStream.read(bufferToRead );

        while (bytesRead > 0) {
            //Add only the total number of bytes read to Bytearrayoutputstream
            blobStream.write(bufferToRead, 0, bytesRead);
            bytesRead = inputStream.read(bufferToRead);                
        }
    } `

Я издевался над InputStream, но обнаружил трудности, насмехаясь над его методом чтения, потому что он принимает буфер в качестве ссылки и копирует байтовый массив в него после чтения.

 @Mock
private BlobInputStream inputStream;


       // Mock
        when(cloudBlobContainer.getBlobReferenceFromServer(anyString())).thenReturn(cloudBlob);
        when(cloudBlob.openInputStream()).thenReturn(inputStream);  

1 Ответ

0 голосов
/ 11 сентября 2018

InputStream очень трудно подделать, не в последнюю очередь из-за его трех read переопределений, а также методов readNBytes и readAllBytes, добавленных в более поздних версиях Java.Если вы закончите с Mockito, вам нужно, чтобы все эти реализации методов взаимодействовали с одними и теми же данными, иначе вы получите хрупкий тест, который может прерваться, как только ваша реализация вызовет разные методы InputStream.Если вы должны использовать тестовый double, вам лучше написать «фальшивку», но нет причин делать это, когда Java имеет встроенный ByteArrayInputStream : вы можете создать свой буфер byte[] (илинапишите вспомогательный метод для его создания в соответствии с вашими требованиями) и замените его на свой InputStream в своем тесте. Этого должно хватить всем, кто приходит к этому вопросу, просто спрашивая о насмешке над InputStream в целом.

final byte[] testFileData = {
    0x74, 0x65, 0x73, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a};
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(testFileData);

К сожалению, это не дает ответа на вопрос о том, как конкретно предоставить тестприспособление для Azure BlobInputStream , что особенно сложно, поскольку BlobInputStream имеет конструктор из четырех аргументов с большим количеством внутренних компонентов Azure .Хорошая новость заключается в том, что начиная с 1.9.5 Mockito предоставляет метод delegatesTo в AdditionalAnswers , задокументированный (с моим собственным акцентом) как:

Ответ, который напрямую перенаправляет вызовыделегат. Делегат может иметь или не принадлежать к тому же типу, что и макет. Если тип отличается, необходимо найти соответствующий метод для типа делегата, в противном случае выдается исключение.

Это означает, что вы можете смоделировать BlobInputStream, создав реальный ByteArrayInputStream и делегировав ему переопределяемые методы.К сожалению, delegatesTo используется для AdditionalAnswers, а не для перечисления ответов (и в любом случае для него требуется параметр экземпляра, который вы не можете предоставить в аннотациях), поэтому вам нужно будет создать свой макет вручную:

BlobInputStream mockInputStream = Mockito.mock(
    BlobInputStream.class,
    AdditionalAnswers.delegatesTo(byteArrayInputStream));

when(cloudBlobContainer.getBlobReferenceFromServer(anyString()))
    .thenReturn(cloudBlob);
when(cloudBlob.openInputStream()).thenReturn(mockInputStream);

Однако, если возможно, это было бы хорошей возможностью разделить ваш код на часть, которая имеет дело с входными потоками Azure против вашего кода приложения, который работает с любым InputStream .Если, например, ваш код принимает BlobInputStream и выполняет код синтаксического анализа или исправления ошибок, вы можете выделить метод handleInputStream(InputStream) и передать свой собственный ByteArrayInputStream, чтобы тщательно его протестировать.Это сводит к минимуму необходимость имитировать BlobInputStream или может полностью исключить его, если вы решите тестировать только обработку BlobInputStream как интеграционный тест с использованием реального бэкэнда.См. Также Mocking Files in Java - Mock Contents - Mockito , где Брайс обсуждает аналогичное разделение между модульными и интеграционными тестами вместо насмешки над экземпляром java.io.File.

...