...
Start by checking out to git tag v1.5-tests_completed_code_refactored with the command
git tag v1.5-tests_completed_code_refactored
We’ll begin by modifying the TextFileSource, replacing references of Iterable<String> with ArrayList<String>
Cut
ArrayList<String> lines = new ArrayList<>();
inloadData( String name, ICollectionLoader func )
(left code line 36) and move it to the top ofloadData( String name );
(right code line 25)In the
loadData( String fname )
method add an extra parameter toloadData(...)
(right code line 31), and modify the method signature to line 35 of the right-hand code fragmentOnce completed make sure the tests still pass -
test_count_chars_in_BasicDataProcessor_no_mocking
So your code should look like this
You should be getting errors in App and TextFileSource if you’ve started from the git tag v1.5-tests_completed_code_refactored. We need to fix the method loadData() in IDataSource so it now matches the revised method signature in TextFileSource, so it should look like this now
Code Block language java public interface IDataSource { public ArrayList<String> loadData( String fname ); public ArrayList<String> loadData( String fname, ArrayList<String> storage, ICollectionLoader func ); }
Notice that we’ve updated the return type of each method so they match the methods in TextFileSource
And App should now look like this
We now need to templatize the class, methods, and parameters so the type is consistent across all three points
You will get an error because the interface is out of sync with what we what the implementation class looks like, so update IDataSource to the following
Code Block language java public interface IDataSource<T> { public <T> T loadData( String fname ); public <T> T loadData( String fname, T storage, ICollectionLoader func ); }
You will still be getting an error in TextFileSource
It is to do with the functor. ICollectionLoader is a Generic and it’s bound to ArrayList<String>, if we don’t specify a generic parameter type for ICollectionLoader, the Java compiler widens it to Object. Also in the line where we create the functor, we cannot use the generic param T because the Java compiler is unable to determine if the c.add() is a method on the type T. So in both cases we need to help the compiler. We need to update IDataSource again to the following
Code Block language java public interface IDataSource<T> { public <T> T loadData( String fname ); public <T> T loadData( String fname, T storage, ICollectionLoader<T> func ); }
We are now telling ICollectionLoader to expect a type T not a type Object
Also update TextFileSource as shown here
In both cases, we are helping the Java compiler
Now complete the process by updating the App class
TextFileSource test file
Now is a good time to add this test file, we should have added this at the beginning
Code Block | ||
---|---|---|
| ||
package com.celestial.mocking_explored;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Stack;
class TextFileSourceTest
{
@Test
void howto_use_loadData_method_with_single_param()
{
TextFileSource<ArrayList<String>> tfl = new TextFileSource<>();
String fname = "C:\\tmp\\KeyboardHandler.java.txt";
ArrayList<String> lines = tfl.loadData(fname);
lines.forEach((element) ->{
System.out.println(">> " + element);
});
}
@Test
void howto_use_LoadData_method_with_3_params()
{
TextFileSource<ArrayList<String>> tfl = new TextFileSource<>();
// We create a lambda expression to do the work in the TextFileLoader
ICollectionLoader<ArrayList<String>> functor = (c, l) -> {
c.add(l);
return c;
};
String fname = "C:\\tmp\\KeyboardHandler.java.txt";
ArrayList<String> data = new ArrayList<>();
ArrayList<String> lines = tfl.loadData(fname, data, functor);
lines.forEach((element) ->{
System.out.println(">> " + element);
});
}
@Test
void howto_use_LoadData_method_with_3_params_using_queue()
{
TextFileSource<ArrayList<String>> tfl = new TextFileSource<>();
// We create a lambda expression to do the work in the TextFileLoader
ICollectionLoader<PriorityQueue<String>> functor = (c, l) -> {
c.add(l);
return c;
};
String fname = "C:\\tmp\\KeyboardHandler.java.txt";
PriorityQueue<String> data = new PriorityQueue<>();
PriorityQueue<String> lines = tfl.loadData(fname, data, functor);
lines.forEach((element) ->{
System.out.println(">> " + element);
});
}
@Test
void howto_use_LoadData_method_with_3_params_using_Stack()
{
TextFileSource<ArrayList<String>> tfl = new TextFileSource<>();
// We create a lambda expression to do the work in the TextFileLoader
ICollectionLoader<Stack<String>> functor = (c, l) -> {
c.push(l);
return c;
};
String fname = "C:\\tmp\\KeyboardHandler.java.txt";
Stack<String> data = new Stack<>();
Stack<String> lines = tfl.loadData(fname, data, functor);
lines.forEach((element) ->{
System.out.println(">> " + element);
});
}
} |