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.