Workshop 11
Workshop 11
JUnit4/TestNG 6
Let us first create a CRUD application first as shown below and later We will learn how
to test Transaction and Controllers using either Junit4 and TestNG
1. Create a Dynamic Web Project named MVCCRUD –Right Click the Project and
Click on Configure-> Convert to Maven Project
2. Create a package named mvccrud.dao inside src folder and create Person.java
as shown below:
package mvccrud.model;
public class Person {
@Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
3. Create a package named mvccrud.dao inside src folder and create
PersonDAO.java interface and put following codes inside it:
package mvccrud.dao;
import java.util.List;
import mvccrud.model.Person;
public interface PersonDAO {
package mvccrud.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import mvccrud.model.Person;
@Repository
public class PersonDAOImpl implements PersonDAO {
return person;
}
}
5. Create a package named mvccrud.service inside src folder and create
PersonService.java interface inside it as shown below:
package mvccrud.service;
import java.util.List;
import mvccrud.model.Person;
public interface PersonService {
}
6. Inside mvccrud.service package create a class named PersonServiceImpl.java
and put following codes inside it:
package mvccrud.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import mvccrud.dao.PersonDAO;
import mvccrud.model.Person;
@Service
public class PersonServiceImpl implements PersonService {
@Autowired
private PersonDAO personDAO;
@Transactional
public void updatePerson(Person p) {
this.personDAO.updatePerson(p);
}
@Transactional
public List<Person> listPersons() {
return this.personDAO.listPersons();
}
@Transactional
public Person getPersonById(int id) {
return this.personDAO.getPersonById(id);
}
@Transactional
public void removePerson(int id) {
this.personDAO.removePerson(id);
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import mvccrud.model.Person;
import mvccrud.service.PersonService;
@Controller
public class PersonController {
public PersonController()
{
System.out.println("Person Controller Called");
}
@RequestMapping("concat")
public String concat(@RequestParam String a, @RequestParam String b,
Model model) {
String result = a + b;
model.addAttribute("result", result);
return "concat";
}
private PersonService personService;
@Autowired(required=true)
@Qualifier(value="personService")
public void setPersonService(PersonService ps){
this.personService = ps;
}
System.out.println("Inside Add");
if(p.getId() == 0){
//new person, add it
this.personService.addPerson(p);
}else{
//existing person, call update
this.personService.updatePerson(p);
}
return "redirect:/persons";
@RequestMapping("/remove/{id}")
public String removePerson(@PathVariable("id") int id){
this.personService.removePerson(id);
return "redirect:/persons";
}
@RequestMapping("/edit/{id}")
public String editPerson(@PathVariable("id") int id, Model model){
model.addAttribute("person", this.personService.getPersonById(id));
model.addAttribute("listPersons", this.personService.listPersons());
return "person";
}
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="personDAO" class="mvccrud.dao.PersonDAOImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="opmcm6718"/>
</bean>
</beans>
10. Make sure you have following codes inside pom.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SpringMVCCRUD</groupId>
<artifactId>SpringMVCCRUD</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.0.3.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
<hibernate.version>4.0.1.Final</hibernate.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.0.100-beta</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
11. Make sure you have following codes inside web.xml file
package unittestcase;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.After;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import
org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests
;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.testng.annotations.Test;
import junit.framework.Assert;
import mvccrud.dao.PersonDAOImpl;
import mvccrud.model.Person;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"demo-servlet.xml"})
@WebAppConfiguration
public class TranTestNg extends AbstractTransactionalTestNGSpringContextTests{
@Autowired
PersonDAOImpl personDAO;
@After
@Test
public void testPhoneLogIsReadable() {
System.out.println("Inside testPhoneLogReadable");
assertTrue("Phone log is not readable.", personDAO.isReadable());
List<Person> lst=personDAO.listPersons();
for(int i=0;i<lst.size();i++)
{
System.out.println(lst.get(i).getId()+"-"+ lst.get(i).getName()
+"-"+lst.get(i).getCountry());
}
}
@Test
@Rollback
@Transactional
public void testAddition()
{
System.out.println("Inside TestAddition");
Person p=new Person();
p.setId(14);
p.setName("Pitu");
p.setCountry("LANKA");
personDAO.addPerson(p);
Person p1=personDAO.getPersonById(14);
Assert.assertNotNull(p1.getId());
}
}
In above example, “testAddition” method tries to record a detail with id=14, but since
this is for testing purpose only, the record is actually not stored on the database. Upper
method testPhoneLogIsReadable() is executed after testAddition( ) and it does not
display record with id=14
To execute above program, Right Click the File->Run As->TestNG Test
Now, let us test the transaction using Junit
Create a class named TranTestJUnit inside unittestcase package as shown below:
package unittestcase;
import java.util.List;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Transactional;
import junit.framework.Assert;
import mvccrud.dao.PersonDAOImpl;
import mvccrud.model.Person;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"demo-servlet.xml"})
@WebAppConfiguration
public class TranTestJUnit {
@Autowired
PersonDAOImpl personDAO;
@After
In above code as well record with id=15 is not really stored on database, which is
verified by upper method execution output. However, during testing record with id=15
seems stored on database as Assert.assertNotNull ( ) will return true.
@RequestMapping("concat")
public String concat(@RequestParam String a, @RequestParam String b, Model
model) {
String result = a + b;
model.addAttribute("result", result);
return "concat";
}
Create concat.jsp file inside WEB-INF/jsp folder and keep following codes inside it:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
${result}
</body>
</html>
Now, we are going to develop a Junit test case that will issue http GET request(/contact)
on above method. Right click on unittestcase package-> New->Other->Select Junit Test
Case-> Create a test case named TestControllerMethod.java and put following codes
inside it:
package unittestcase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.junit.*;
import junit.framework.Assert;
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test()
MockMvcBuilders.webAppContextSetup(this.wac).build();
Assert.assertNotNull(mockMvc);*/
this.mockMvc.perform(post("/concat").param("a",
"red").param("b", "apple"))
.andExpect(status().isOk())
.andExpect(model().attribute("result", "redapple"))
.andExpect(forwardedUrl("/WEB-INF/jsp/concat.jsp"))
.andDo(MockMvcResultHandlers.print());
}
}
Above code will send “red” and “apple” as parameteran the “concat” method inside
TestController class. The method concatenates the two string and will return back to the
client.
To Execute above program, Right Click on it->Run As-> Junit Test
You will see following output on the console
MockHttpServletRequest:
HTTP Method = POST
Request URI = /concat
Parameters = {a=[red], b=[apple]}
Headers = {}
Handler:
Type = mvccrud.controller.PersonController
Async:
Was async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = concat
View = null
Attribute = result
value = redapple
FlashMap:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = /WEB-INF/jsp/concat.jsp
Redirected URL = null
Cookies = []
Mocks vs Stubs
If you want to test a method that uses an object of another class, then in order to test
such method there exists two different approaches.
1. Create Mock object of Dependent class and test that method
2. Create Stub object of Dependent class and test that method
Mocking
1. Inside unittest package, create a class named ClassOne.java and put following
codes inside it.
package unittest;
2. In the same class, create another class named ClassTwo.java and put the
following codes inside it.
package unittest;
public class ClassTwo {
}
If we want to test “twoMessage( )” method as shown above, we have to know
that this particular method is dependent on another object named “one” that
belongs to ClassOne.java class.
1. ClassOne mockOne=Mockito.mock(ClassOne.class);
2. Mockito.when(mockOne.oneMessage()).thenReturn("ok");
3. ClassTwo two =new ClassTwo(one);
4. assertEquals("ok",two.twoMessage());
}
In above code, (line 1)we have not created actual object of ClassOne object rather
mock object of ClassOne named “mockOne” and passed it to ClasstTwo in line no
3. Line No 2, will cause oneMessage( ) method to return always “ok” when get
called. LineNo 4, performs unit testing of “twoMessage” method.
To Run above program. Right Click on TestMock->Run As-> Junit Test and will
successfully be executed
Stub/ Stubbing Beans While Testing
In above example, we have created mock object of ClassOne and passed it to the
ClassTwo object since the method to be tested( i.e. “twoMessage” of ClassTwo)
uses or is dependent on ClassOne object.
Create a class named StubTest inside unittestcase package and put following codes
inside it.
package unittestcase;
}
In above example, we have passed stub object to ClassTwo instead of mock.
ClassOneStub does not fully incorporate exact source code of ClassOne, rather only
minimal required code only.
ClassOneStub is kept inside unittest package has following code:
package unittest;
Click on Run Button. War file will be created that we will keep on PWS(Pivotal
Web Service)
4. Open Command prompt and type following command to logon to PWS
cf login -a api.run.pivotal.io -u [email protected] -p
opmcm6718 -o opmcm
5. Go to target folder of your MVCCRUD application and type following command to
push or deploy MVCCRUD application to PWS.
6. Click on URL mentioned on Route column of your App as shown below, your
APP will be executed.
Deploying Spring Web Application on Heroku
heroku plugins:install https://github.com/heroku/heroku-deploy
https://signup.heroku.com/dc
2. Login to heoku from your created account
3. Click on NewApp and give your App a new name “mvccrud”
4. Download and install toolblet from following URL:
https://devcenter.heroku.com/articles/getting-started-with-java#set-up
5. Create war file of the mvccrud application as shown previously for pivotal web
service application
6. Open Command prompt and type heroku login and provide your email
address and password
7. In the same command prompt type the following URL:
10. asdsad