3. Mocking basics

Mocking is one of the most powerful techniques in unit testing, which can be leveraged to solve complex problems in testing. There can be cases as mentioned in previous videos, that, one needs to test some implementation with 3rdparty functionality. However, the problem is that, one can not control these functionalities totally. To overcome this hurdle, one must use mocking.
Supporting video
Example 1.
The best way to understand mocking is to check examples of mocking, therefore we turn to sample_2 and more specifically, to NetworkConnection.java and NetworkConnectionTest.java.
First let’s understand what NetworkConnection.java implementation is about.
It has three members,
mUrl, mCharset, mQuerydenoting the URL that we plan to connect to, the coding charset that will be used during the established connection, and the query used to encode the different parameters during the connection establishment.The constructors doesn’t need much description, however the function
public String GetHttpRequest() throws MalformedURLException, IOExceptiondoes need some further clarity.
Supporting video
The GetHttpRequest() function
To test this GetHttpRequest() function is a tricky one.
- It starts by
URLConnection vConnection = new URL( mUrl + "?" + mQuery).openConnection();which is basically opening the connection to the remote website that was specified in the member string. - Next
vConnection.setRequestProperty("Accept-Charset", mCharset);sets the properties of the connection request, in our case it isUTF-8 - After the connection has been established the code waits for a response by
InputStream vResponse = vConnection.getInputStream( );and saves it into a local variable - As a last step, the
InputStreamis traversed with a ScannerScanner scanner = new Scanner( vResponse )using\\Aas a delimiter.
To test this function one must overcome massive amount of hurdles to have it as an actual unit test. Lets start at the basics first to reach the point, where we are braced with the knowledge to test such complicated chain-of-mocks examples.
Mocking a simple function
First check out the NetworkConnectionTest.java
- This test class start by doing a
BlackMagic()as a Setup function by instantiating theNetworkConnectionclass - The
HttpRequestReturnsNotNull()test case simply tests if theGetHttpRequest()function returnsStringcontaining a space - Now the most interesting for is the
HttpRequestReturnsNull()where the actual mocking happens- First we need to specify, which class we would like to mock
mNetworkConnection = mock( NetworkConnection.class ); - The next step is
when( mNetworkConnection.GetHttpRequest()).thenReturn(" ");to alter the functionality of the original class - Asserting against the altering of the original functionality by
assertEquals(" ", mNetworkConnection.GetHttpRequest() );
- First we need to specify, which class we would like to mock
This simple example shows that, basically with mocks we can alter the behaviour of any function inside our implementation. However, the first example is much more complicated than that, because there are some internal local variables initialized by 3rdparty functionalities, which makes mock-injection extremely hard.
Problems with testing GetHttpRequest() function
The main issues with public String GetHttpRequest() throws MalformedURLException, IOException are the following
- The first initialization is complicated as it is.
URLConnectiontype on the left-hand-side initialized by a newURLclass’sopenConnection()function. This will be extremely challenging because we can’t access these from the outside, these are local functionalities and local variables. Further,URLConnectionispublic abstract classwhich is hard to mock - The next invocation, setting the rquest property on a local variable, which is challenging to handle
- Forward, the inputstream handling is based on
URLConnectiontype local variable, where thegetInputStream()function needs to be mocked - In the
tryblock aScannertype is instantiated, where this needs to be mocked as well where the fact,public final classjust complicates mocking - Inside the scanning
tryblock only theuseDelimiter()function needs to be mocked, however it is a bit complicated as discussed before
TL;DR this task is challenging because there is the technique chain-of-mocks that need to be applied sequentally complicated by abstract and final classes that need to be mocked out.
Supporting video
Tasks 1.
Implement a mocking strategy to gain control over all the external functionality inside GetHttpRequest()
URLandURLConnectionneed to be mocked from the outsidesetRequestProperty()has to be mocked as well alongside withgetInputStreamInputStreamclass has to be mockedScannerclass has to be mocked with theuseDelimiter()andnext()function as well