Проблема с имитацией во многих случаях заключается в том, что методы создают свои собственные зависимости, а не вводят их или вызывают вызывающий метод службы, создающий их.Я предлагаю вам немного реорганизовать свой код, извлекая BufferedReader
создание в метод сервиса:
package de.scrum_master.stackoverflow.q56772468
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.SimpleType
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path
class CdmFile {
String readFileContents(Path filePath) {
StringBuilder fileContents = new StringBuilder()
BufferedReader br = createBufferedReader(filePath)
String line
while ((line = br.readLine()) != null) {
fileContents.append(line).append('\n')
}
fileContents
}
void eachLineInFileAsString(
Path filePath,
@ClosureParams(value = SimpleType, options = ['java.lang.String']) Closure applyLine
) {
BufferedReader br = createBufferedReader(filePath)
String line
while ((line = br.readLine()) != null) {
applyLine.call(line)
}
}
protected BufferedReader createBufferedReader(Path filePath) {
Files.newBufferedReader(filePath, StandardCharsets.UTF_8)
}
}
Теперь макетирование довольно просто, и вам больше не нужен файл тестового ресурса (только еслиВы хотите выполнить интеграционный тест без макетов):
package de.scrum_master.stackoverflow.q56772468
import spock.lang.Specification
import java.nio.charset.StandardCharsets
import java.nio.file.NoSuchFileException
import java.nio.file.Path
import java.nio.file.Paths
class CmdFileTest extends Specification {
private static final String filePath = 'mock/cdmTestFile.txt'
private static final String fileContent = """
I heard, that you're settled down
That you found a girl and you're, married now
I heard, that your dreams came true
I guess she gave you things
I didn't give to you
""".stripIndent()
private CdmFile cdmFile
void setup() {
cdmFile = Spy() {
createBufferedReader(Paths.get(filePath)) >> {
new BufferedReader(
new InputStreamReader(
new ByteArrayInputStream(
fileContent.getBytes(StandardCharsets.UTF_8)
)
)
)
}
}
}
def "non-existent file leads to exception"() {
given:
Path notRealPath = Paths.get('notreal.txt')
when:
cdmFile.readFileContents(notRealPath)
then:
thrown NoSuchFileException
}
def "read file contents into a string"() {
given:
Path testFilePath = Paths.get(filePath)
when:
String fileContents = cdmFile.readFileContents(testFilePath)
then:
fileContents.contains("your dreams came true\nI guess")
}
def "handle file content line by line"() {
given:
def result = []
def closure = { line -> result << line }
Path testFilePath = Paths.get(filePath)
when:
cdmFile.eachLineInFileAsString(testFilePath, closure)
then:
result == fileContent.split("\n")
}
}
Обратите внимание, что я использую здесь Spy()
, то есть оставляю исходный объект CdmFile
нетронутым и просто указываю на метод обслуживания createBufferedReader(..)
при вызове с точно параметром Paths.get(filePath)
.Для других путей вызывается оригинальный метод, который важен для несуществующего теста файлов или если вы хотите добавить тесты, связанные с загрузкой файлов реальных ресурсов, как в вашем собственном примере.
Всякий раз, когда трудно проверитькласс или компонент, которые трудно внедрить в макеты или иным образом изолировать тестируемый объект, что является причиной для рефакторинга кода вашего приложения для лучшей тестируемости.Если все сделано правильно, это также должно привести к лучшему разделению интересов и лучшей компонентизации.Если ваши тесты становятся очень сложными, надуманными, хрупкими и трудными для понимания и сопровождения, это, как правило, запах, и вместо этого вам следует реорганизовать код приложения.