How do I use unit test code that uses goava goava libraries, especially in the io package?

Many functions in guava are provided by static methods. I did not understand how to combine the use of guava libraries and the good practice of dependency injection.

For example, if I used

Files.readLines(File, Charset) 

then I find it difficult for me to write unit test, which does not concern the file system, which I like only for integration testing.

Perhaps I can write an adapter for everyone I’m interested in? But it may end up with a lot of work ...

It seems strange to me that guava libraries belong to the same set of people who provide guice and write blog posts like this

+7
source share
6 answers

Wow, scary static methods. I heard that JMockit is able to mock statics, but I never tried it myself. Usually I use this adapter.

 public class FilesAdapter { private final File file; public FilesAdapter( File file ) { this.file = file; } public List<String> readLines( Charset charset ) { return Files.readLines( file, charset ); } } 

You can optionally have a FilesAdapter implements the interface, although since this is an object for one purpose, I usually did not.

GUICE is capable of injecting specific objects, and mocking frameworks like JMock2 and Mockito can mock concrete. This is all a matter of scientists, and different people will have different opinions.

If you used GUICE, you would have wrapped this guy in a factory for a good mood.

 public class FilesAdapter { private final File file; @Inject protected FilesAdapter( @Assisted File file ) { this.file = file; } public List<String> readLines( Charset charset ) { return Files.readLines( file, charset ); } public interface Factory { FilesAdapter create( File file ); } } 
+4
source

We provided the common.io library as a stop until you finally get the real API of the proper files in JDK 7. This library will be interface-based and very convenient for testing.

+3
source

Powermock allows you to mock static methods .

We use it here and there, and I can testify that it works.

+2
source

You can isolate static dependency from your own method (which can then be redirected for testing purposes, as shown below). Typically, an isolated method has “protected” visibility.

 import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.io.File; import org.junit.Before; import org.junit.Test; public class FileUtilsTest { private static final String[] TEST_LINES = { "test 1", "test 2", "test 3" }; private static final File TEST_FILE = new File("/foo/bar"); private FileUtils fileUtils; /** * Configure reusable test components */ @Before public void setUp() { fileUtils = spy(new FileUtils()); when(fileUtils.getLines(any(File.class))).thenReturn(TEST_LINES); } /** * Ensure the {@link FileUtils#countLines(File)} method returns the correct line count (without hitting the * file-system) */ @Test public void testCountLines() { assertEquals(3, fileUtils.countLines(TEST_FILE)); } /** * The class we want to test */ public static class FileUtils { /** * Method that we want to test */ public int countLines(final File file) { return getLines(file).length; } /** * Static dependency isolated to a method (that we can override, for test purposes) */ public String[] getLines(final File file) { return Files.readLines(file); } } /** * Poorly written utility class with hard-to-test static methods */ public static class Files { public static String[] readLines(final File file) { // In reality, this would hit the file-system return new String[] { "line 1" }; } } } 
0
source

First of all, why not just let your device’s tests relate to the file system? Usually reading small local test files in several tests does not add a noticeable delay to the test run.

But if you really don't want to touch the file system, then just scoff at it. For example, the following JMockit test should work:

 @Test public void someTest() { new Expectations() { @Mocked Files files; @Input List<String> lines = asList("Line 1", "Another line", "..."); }; // Called from code under test: List<String> lines = Files.readLines(someFile, charSet); // These "lines" will be the same as the "@Input" lines. // asserts... } 
-one
source

Provide your own stubs for the static methods you call, and let the class loader “insert” them for you.

In general, this is not a problem with DI and mocks. Some dependencies simply do not need to explicitly inject injections if they are common enough to be considered dependencies, and you are pretty sure that they work as advertised. I think Guwa falls into this category. In the same way, bullying does a great job of manipulating states that static methods should not throw off on all sides, so you won’t get much, even if you manage to mock them.

-one
source

All Articles