2. What is TDD?
Software development process.
Test-first programming concepts.
3.
4. Advantages
Code quality
Focus and better understanding of requirements
Modular, loosely coupled code
5. Shortcomings
TDD brings in a sense of confidence, but not in the cases when developer
misunderstands the requirements.
Bad written tests are hard to maintain. Tests need as much attention as the
code itself if not more.
6. How to TDD with Spring?
Basics don’t change.
STEPS:
Code to interface(e.g. StudentService) , then code the skeleton concrete
implementation(e.g. StudentServiceImpl) without details. Say, we need to write a method
which takes studentId and classId as arguments and returns a Boolean indicating whether
the student is registered for a class. In this example, in the concrete implementation as a
first step should just return false.
Create your test class. – Add a test case.
In the test method for above scenario: pass in a valid studentId who is registered to a
class, you would assert for true, but it returns false. – Fail a test case.
7. How to TDD with Spring?
Now, write some code in the class to pass the test case i.e. access the Student
DAO to make sure given a valid studentId and classId, it returns true – Pass the
test case.
Consider the requirements once again like what should be returned if studentId
passed is null or classId is null(assuming non-primitives are passed). – Write tests
for these cases, fail again. Forces you to think from business/functional
perspective.
Make necessary changes to your implementation to handle these cases. –
Refactoring.
Repeat from 1st step again.
8. Useful Unit testing Annotations
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(context xml loaded from classpath)
or
@ContextConfiguration(classes={StudentServiceImplTestConfig.class})
Best practice: Create as minimum number of beans as possible as it’s a unit
test case and shouldn’t hinder your CI(Continous Integration).
9. Sample Spring Unit test
//Reference from spring documentation
package com.example;
@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration(classes=OrderServiceConfiguration.class, loader=AnnotationConfigContextLoader.class)
Public class OrderServiceTest{
@Autowired
Private OrderService orderService;
@Test
Public void testOrderService(){
//test the service.
}
}
10. Resolving Dependencies of beans not under
test
Scenario: Assume there is a “StudentService” bean which we talked about
and has a new requirement - when the students logins using the studentId,
it needs to return class ids the student is registered.
Desired output: If the studentId doesn’t exist, throw an error message
saying “Student ID doesn’t exist”. Else, return the class ids.
Dependency: Now, it has a dependency on a Student DAO to check whether
studentID exists and if it does, get the class ids.
Best practice: Write tests in isolation i.e. if we are testing StudentService,
then test only StudentService and not StudentDao.
13. Scenario
public List<integer> getClassIds (Integer studentId) throws
InvalidStudentException{
if(studentId== null ||studentId.isEmpty()){
throw new InvalidStudentException(”Student ID is
empty, please enter it");
}
if(studentDao.checkValidStudent(studentId))
return
studentDao.getClassIdsByStudentId(studentId);
else
throw new InvalidUserException("Invalid student
ID");
}
14. As we can see, there is dependency on DAO, we can mock DAO something like
below:
StudentDao mockStudentDao = Mockito.mock(StudentDao.class);
when(mockUserDao.checkValidStudent(”1234")).thenReturn(true);
List<Integer> listOfClassIds = new ArrayList<Integer>();
listOfClassIds.add(101);
listOfClassIds.add(102);
when(mockUserDao.getClassIdsByStudentId(”1234")).thenReturn(listOfClassId
s);
15. Test case
@Test
public void testClassIds(){
List<Integer> listOfClassIds = new ArrayList<Integer>();
listOfClassIds.add(101);
listOfClassIds.add(102);
Assert.assertEquals("Display class ids for a valid
student”,listOfClassIds, studentService.getClassIds(”1234"));
} //Now this takes care of studentDao as it’s mocked.
16. Mock HTTP
Mocks for various HTTP related stuff:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/mo
ck/web/
17. Code Coverage
Measure of how much code is tested.
Very useful when you didn’t start the project with TDD, but adding tests
later. It gives you a measure of how effective your tests are in covering your
code.
18. EclEmma
Java code coverage tool for Eclipse.
Drill-down of coverage to method level.
Source high-lighting.