Assignment #3: Mocking

Mock A3 doc

Part A

Get Eclipse and create a new maven project. Then add dependencies in the pom.xml file. For some reason I get two errors, first line of the pom.xml saying something cannot find the external dependency. However, it works when I check if the JUnit is there and working…

Part B

ListTestTest.java:

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
 
import java.util.List;
 
import org.junit.Test;
import org.mockito.Mockito;
 
public class ListTestTest {
 
	@Test
	public void letsMockListSize() {
		List list = mock(List.class);
		when(list.size()).thenReturn(10);
		assertEquals(10, list.size());
	}
 
	@Test
	public void letsMockListSizeWithMultipleReturnValues() {
		List list = mock(List.class);
		// TODO: Make this test pass using one line of code. Hint: look at the Mockito documentation
		// for "thenReturn"
		assertEquals(10, list.size()); // First Call
		assertEquals(20, list.size()); // Second Call
	}
 
	@Test
	public void letsMockListGet() {
		List<String> list = mock(List.class);
		when(list.get(0)).thenReturn("0th element");
		assertEquals("0th element", list.get(0));
		// Does the next line pass or fail? Why? If it fails, how do we make it pass? What is the value of list.get(1)?
		// assertNull(list.get(1));
	}
 
	@Test
	public void letsMockListGetWithAny() {
		List<String> list = mock(List.class);
		Mockito.when(list.get(Mockito.anyInt())).thenReturn("this is an int");
		assertEquals("this is an int", list.get(0));
		assertEquals("this is an int", list.get(1));
	}
}

For each of the four unit tests, you can see the line

List list = mock(List.class)

To make letsMockListSizeWithMultipleReturnValues() pass, add this line after the commented line:

when(list.size()).thenReturn(10, 20);

Now run the tests again and it should pass

By default, for all methods that return a value, a mock will return either null, a primitive/primitive wrapper value, or an empty collection, as appropriate. For example 0 for an in/Integer and false for a boolean/Boolean.

Once stubbed, the method will always return a stubbed value, regardless of how many times it is called, unless overridden by specifying another value through another stub.

The last stubbing is more important - when you stubbed the same method with the same arguments many times. Other words: the order of the stubbing matters but it is only meaningful rarely, e.g. when stubbing exactly the same method calls or sometimes when argument matchers are used, etc.

Part C - Mocking a class implementation

Now that we have mocked the List class from Java, we will see how mocking a dependency works. In real life, rather than mocking a List object, we would have instances of an actual one. You can find the following Java files in Assignmemt3.zip.

TodoService.java interface

TodoBusinessImplMockitoTest.java test case

TodoBusinessImpl.java class

After you finish all the experiment parts (part A to part C), you need to answer the corresponding questions in the following report and provide appropriate screenshots and / or source files to support your answers. 

Please submit it as a PDF file on moodle with the file name of ‘Assignment3_yourname_yourstudentID.pdf’.

Questions

Question 3 2%: Copy the three files above into the same test directory as Part C

Observe the three files and run the unit tests in TodoBusinessImplMockitoTest.java. Describe the interactions.

Observing the provided files and running the unit tests in TodoBusinessImplMockitoTest.java gives us insights into the interactions between the classes and the mocked dependencies.

  1. TodoService.java (interface):
    • This interface defines a contract for retrieving and deleting todos. It includes methods retrieveTodos(String user) and deleteTodo(String todo).
  2. TodoBusinessImpl.java (class):
    • This class implements business logic related to todos. It has a dependency on TodoService interface.
    • The constructor injects a TodoService implementation into the TodoBusinessImpl instance.
    • It contains methods:
      • retrieveTodosRelatedToSpring(String user): Retrieves todos related to “Spring” for a given user.
      • deleteTodosNotRelatedToSpring(String user): Deletes todos not related to “Spring” for a given user.
  3. TodoBusinessImplMockitoTest.java (test case):
    • This test case class verifies the behaviour of TodoBusinessImpl using Mockito for mocking TodoService.
    • It mocks the TodoService interface using Mockito’s mock() method.
    • It stubs the behaviour of the retrieveTodos(String user) method of the mocked TodoService to return a predefined list of todos when invoked with a specific user.
    • It then tests the retrieveTodosRelatedToSpring(String user) method of TodoBusinessImpl to ensure it filters todos related to “Spring” correctly.
    • The test verifies that the retrieveTodosRelatedToSpring(String user) method returns the expected number of todos related to “Spring” for a given user.

Interactions:

  • The TodoBusinessImpl class interacts with the TodoService interface to retrieve and filter todos based on certain criteria (in this case, whether the todo contains “Spring” in its description).
  • In the test case, Mockito is used to mock the behaviour of the TodoService interface, specifically the retrieveTodos(String user) method, to return predefined todos when called with a specific user.
  • The TodoBusinessImplMockitoTest class then verifies that the retrieveTodosRelatedToSpring(String user) method of TodoBusinessImpl correctly filters todos related to “Spring” based on the mocked behaviour of TodoService.
  • No actual deletion of todos is performed as the TodoService is mocked, and only retrieval behaviour is stubbed for testing purposes.