...
Write the unit test first for a CUT called FileLoader
. It should only have one public method on it. Once the test is written develop the CUT to pass the test.
public int LoadFileloadFile(string fname)
The above function should load a text file from the disk, and return the number or characters in it.
Your test should specify the input the file name including its path, and the number of characters expected be in the file.
Assert on the actual file length (number of characters in the file) against the expected file length (number of characters read from the file)
In the production class we suggest you use something like File.
ReadLinesreadAllLines()
Once you have completed the above test and production code, think about this question
...
In the //Act part of the test, we want to write something like this
Code Block language java // act int bytesRead = cut.loadFile((fname) -> { List<String> result = null; try { result = Files.readAllLines(Paths.get(fname), StandardCharsets.UTF_8); } catch (IOException e){} return result; });
Reading the API guides we see that
File.readAllLines()
returns aList<string>
, so let's change the code to match thisCode Block language java package com.celestial.mockito.filetodb; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; public class FileLoaderTest { // Redesign the FileLoader so that the machenism to load files up can be // passed in as a lambda - still titghtly coupled the file system @Test public void load_all_of_file_using_inbuilt_Files_type_as_lambda() { // arrange String fileToLoad = "c:/tmp/KeyboardHandler.txt"; FileLoader cut = new FileLoader(fileToLoad); int expectedBytesRead = 10; //1371; List<String> pretendFileContent = new ArrayList<>(); pretendFileContent.add("Hello"); pretendFileContent.add("world"); MockedStatic<Files> ff = Mockito.mockStatic(Files.class); ff.when(() -> Files.readAllLines(Paths.get(fileToLoad), StandardCharsets.UTF_8)).thenReturn(pretendFileContent); // act int bytesRead = cut.loadFile((fname) -> { List<String> result = null; try { result = Files.readAllLines(Paths.get(fname), StandardCharsets.UTF_8); } catch (IOException e){} return result; }); // assert assertEquals(expectedBytesRead, bytesRead); } }
At line 3228, we are using Mockito’s
mockStatic()
to mock a Static classAt line 3329, we setup the expectation
So we need to design a loadFile() method that takes as a parameter a block of code that can read the file from any source.
public int LoadFile(string fname, ILoadFile func)
Create a new interface called
Code Block language java package com.celestial.mockito.filetodb; import java.util.List; /** * * @author selvy */ @FunctionalInterface public interface ILoader { List<String> loadFile(String fname); }
Modify FileLoader so it has this additional functionality
Code Block language java public List<String> getLines() { return lines; } int loadFile(ILoader func) { lines = func.loadFile(fileToLoad); return calculateFileSize(); } ...
...
In this implementation of the test System.IO.File we want to use java.nio.file.Files
object. But wait, Systemjava.nio.
IOfile.
FileFiles.ReadLines()
is a class-level operation and not an object-level operation. Most mocking frameworks struggle with mocking class-level methods.
...