Wednesday, August 5, 2009

Shopping Cart Web Application - Part 10 - AJAX

Introduction
Asynchronous JavaScript and XML (AJAX) is a group of interrelated web development techniques used for creating interactive web applications or rich Internet applications. With Ajax, web applications can retrieve data from the server asynchronously in the background without interfering with the display and behavior of the existing page. Data is retrieved using the XMLHttpRequest object or through the use of Remote Scripting in browsers that do not support it. Despite the name, the use of JavaScript and XML is not required, and they do not have to be used asynchronously

What you need before we get started

What we will cover
  • Advantages of AJAX
  • RichFaces
  • Limitations and rules
  • Shopping cart

Level
  • Beginner

Advantages of AJAX
  • Nice user experience - AJAX gives the user a way to interact with a website without having to wait for lengthy refreshes on a website. Sections of pages can be reloaded individually without having to reload the whole page
  • Less bandwidth used - instead of the full contents of the HTML page being sent to and from the server only the required information is transmitted. The network utilization is minimized and quicker operations occur
  • Limited processing on the server — Users may perceive the application to be faster or more responsive because only the necessary data is sent to the server, the server is not required to process all form elements. By sending only the necessary data, there is limited processing on the server. There is no need to process all form elements, process the viewstate, send images back to the client, and no need to send a full page back to the client

RichFaces 
RichFaces is an open source framework that adds Ajax capability into existing JSF applications without resorting to JavaScript. RichFaces leverages JavaServer Faces framework including lifecycle, validation, conversion facilities and management of static and dynamic resources. RichFaces UI library contains components for adding rich user interface features to JSF applications. Create a modern rich user interface look-and-feel with skins-based technology. RichFaces UI components come ready to use out-of-the-box, so developers save their time and immediately gain the advantage of the mentioned above features in Web applications creation. As a result, usage experience can be faster and easily obtained.

RichFaces allows to define (by means of JSF tags) different parts of a JSF page you wish to update with an Ajax request and provide a few options to send Ajax requests to the server. JSF page doesn't change from a "regular" JSF page and you don't need to write any JavaScript or XMLHTTPRequest objects by hands, everything is done automatically.

  • Ajax Filter - RichFaces uses a filter for a correction of code received on an Ajax request. In case of a "regular" JSF request a browser makes correction independently. In case of Ajax request in order to prevent layout destruction it's needed to use a filter, because a received code could differ from a code validated by a browser and a browser doesn't make any corrections
  • Ajax Action Components - There are Ajax Action Components: <a4j:commandButton>, <a4j:commandLink>, <a4j:poll>, <a4j:support>, etc. You can use them to send Ajax requests from the client side
  • Ajax Containers - AjaxContainer is an interface that describes an area on your JSF page that should be decoded during an Ajax request. AjaxViewRoot and AjaxRegion are implementations of this interface
  • JavaScript Engine - RichFaces JavaScript Engine runs on the client-side. It knows how to update different areas on your JSF page based on the information from the Ajax response. Do not use this JavaScript code directly, as it is available automatically

Limitations and Rules
  • Any Ajax framework should not append or delete, but only replace elements on the page. For successful updates, an element with the same ID as in the response must exist on the page. If you'd like to append any code to a page, put in a placeholder for it (any empty element). For the same reason, it's recommended to place messages in the "AjaxOutput" component (as no messages is also a message)
  • Don't use <f:verbatim> for self-rendered containers, since this component is transient and not saved in the tree
  • Ajax requests are made by XMLHTTPRequest functions in XML format, but this XML bypasses most validations and the corrections that might be made in a browser. Thus, create only a strict standards-compliant code for HTML and XHTML, without skipping any required elements or attributes. Any necessary XML corrections are automatically made by the XML filter on the server, but lot's of unexpected effects can be produced by an incorrect HTML code
  • The RichFaces ViewHandler puts itself in front of the Facelets ViewHandlers chain
  • RichFaces components uses their own renderers. On the Render Response Phase RichFaces framework makes a traversal of the component tree, calls its own renderer and puts the result into the Faces Response

Shopping Cart Application

1. RichFaces Filter
I added the RichFaces filter to the web deployment descriptor:

<filter>
 <display-name>RichFaces Filter</display-name>
 <filter-name>richfaces</filter-name>
 <filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
 <filter-name>richfaces</filter-name>
 <servlet-name>Faces Servlet</servlet-name>
 <dispatcher>REQUEST</dispatcher>
 <dispatcher>FORWARD</dispatcher>
 <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

2. RichFaces components
I will only be adding AJAX components to the items.jspx page. The other pages can stay as they are as there isn’t a need to add any AJAX components to them. The first thing I did was add the RichFaces tag library xml namespaces to the items.jspx page. Below is the completed items.jspx page. I you compare it to the previous version you would realize that there is very little change, I just replaced most of the standard JSF components with RichFaces components.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
    xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    version="2.0">
<ui:composition template="/template.jspx">
 <ui:define name="body">
  <h:outputText id="headingOutTxt" value="#{msg.items_txt_heading}"
   styleClass="headingOutputText" />
  <a4j:form id="itemListFrm">
   <rich:dataTable id="itemsTbl" var="items" value="#{pc_Items.items}"
    binding="#{pc_Items.itemsTable}" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    headerClass="dataTableHeader">
    <rich:column id="nameCol">
     <f:facet name="header">
      <h:outputText id="nameHeaderOutTxt"
       value="#{msg.items_txt_name_col_header}" />
     </f:facet>
     <h:outputText id="nameOutTxt" value="#{items.name}" />
    </rich:column>
    <rich:column id="descriptionCol">
     <f:facet name="header">
      <h:outputText id="descriptionHeaderOutTxt"
       value="#{msg.items_txt_description_col_header}" />
     </f:facet>
     <h:outputText id="descriptionOutTxt" value="#{items.description}" />
    </rich:column>
    <rich:column id="priceCol">
     <f:facet name="header">
      <h:outputText id="priceHeaderOutTxt"
       value="#{msg.items_txt_price_col_header}" />
     </f:facet>
     <h:outputText id="priceOutTxt" value="#{items.price}">
      <f:convertNumber pattern="#{msg.currency_pattern}" />
     </h:outputText>
    </rich:column>
    <rich:column id="addActionCol">
     <a4j:commandLink id="buyLnk" value="#{msg.items_lnk_buy}"
      action="#{pc_Items.addItemToBasket}" reRender="basketTbl" />
    </rich:column>
   </rich:dataTable>
   <p />
   <h:outputText id="basketOutTxt" value="#{msg.items_txt_basket}" />
   <p />
   <rich:dataTable id="basketTbl" var="basketItem" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    value="#{shoppingViewHelper.basket.basketItems}"
    binding="#{pc_Items.basketTable}">
    <rich:column id="basketItemCol">
     <f:facet name="header">
      <h:outputText id="basketTblHeaderOutTxt"
       value="#{msg.items_txt_basket_item_col_header}" />
     </f:facet>
     <h:outputText id="basketItemOutTxt" value="#{basketItem.item.name}" />
    </rich:column>
    <rich:column id="basketItemQuantityCol">
     <f:facet name="header">
      <h:outputText id="basketTblQuantityOutTxt"
       value="#{msg.items_txt_basket_quantity_col_header}" />
     </f:facet>
     <h:outputText id="basketItemQuantityOutTxt" value="#{basketItem.quantity}" />
    </rich:column>
    <rich:column id="basketItemPriceCol">
     <f:facet name="header">
      <h:outputText id="basketTblPriceOutTxt"
       value="#{msg.items_txt_basket_price_col_header}" />
     </f:facet>
     <h:outputText id="basketItemPriceOutTxt" value="#{basketItem.price}" />
    </rich:column>
    <rich:column id="removeActionCol">
     <a4j:commandLink id="removeLnk" value="#{msg.items_lnk_remove}"
      action="#{pc_Items.removeItemFromBasket}" reRender="basketTbl" />
   </rich:column>
   </rich:dataTable>
   <p />
   <h:commandButton id="checkoutBtn" value="#{msg.btn_checkout}"
    action="#{pc_Items.checkout}" />
   <rich:messages errorClass="errorText" /> 
  </a4j:form>
 </ui:define>
</ui:composition>
</jsp:root>

3. Items backing bean
There are two very small changes we need to make to the Items backing bean (Items.java). Our itemsTbl datatable and our basketTbl datatable are bound to javax.faces.component.html.HtmlDataTable objects within our Items.java backing bean. Because our datatables are no longer standard JSF datatables but RichFaces datatables we need to change this binding from a javax.faces.component.html.HtmlDataTable to a org.richfaces.component.UIDataTable.

The end result:



As you can see it was actually pretty simple to get up and running. Please visit the RichFaces demo site to see the full range of RichFaces components in action. You may have to register on their website to view the demo but it is well worth it. Also please read through the RichFaces developers guide . It is very useful reference manual that contains a comprehensive guide to all of the RichFaces components.

Tuesday, August 4, 2009

Shopping Cart Web Application - Part 9 - Advanced Test Cases

Introduction
Our application has grown in size and complexity since the last time we created our unit test for the shopping service class. This is what I would like to do:
  • Integrate our test case with Spring – this is pretty cool, instead of creating and initializing our objects manually or performing any JNDI looking ups ourselves (that is if we did need to do that) we will let Spring take care of this for us using our existing Spring bean configuration files we created in the previous tutorial.
  • Mock objects – In some cases it is very difficult to test a service. In our case it isn’t because all we are doing is creating an instance of the service ourselves but what if the instance of the service existed on a remote server and you needed to use a remote call to lookup that instance? It adds additional overhead to your test case. For one it relies on this remote service to be available at the time the test is run and two it requires additional resources in order to perform this lookup. An alternative to testing the service is to create a mock of the service and predict the outcome of the test. So you don’t actually test the service implementation but your very own mock that is based on the service interface. This sounds like a lot of work but it isn’t actually thanks to a third party library we are going to use called EasyMock.
  • Database integration testing – We touch on an integration test for testing transactions with the database. We will be using spring as well as a third party library called DBUnit.

What you need before we get started
  • ShoppingCartAdvancedTestCasesPart9 sample application. - This is an Eclipse archive file that contains one Eclipse project. Please import this project into your Eclipse environment.
  • You will need the previous third party libraries that were mentioned and used in earlier parts to this tutorial
  • The following libraries need to be added to your existing Libs project:

What we will cover
  • Spring integration
  • Mock object tests
  • Database integration tests

Level
  • Intermediary

Spring Integration
We are going to use Spring for two purposes, the first is for our Shopping service class. We will let Spring manage the creation and initialization of this object for us so. We will also make use of our existing spring bean configuration file to initialize our service class. Secondly we are going to use Spring to create test data for us so that we can use it in our test case. To do this we will create a Spring bean configuration file specifically for our tests. I have put it under our test folder and called it shoppingcart-test.xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  <bean id="shoppingService" class="com.mydomain.shoppingcart.service.impl.ShoppingManager">
    <property name="itemDao">
      <ref bean="itemDao" />
    </property>
    <property name="basketDao">
      <ref bean="basketDao" />
    </property>
  </bean>
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="shoppingCartDataSource" />
  </bean>
  <import resource="classpath:shoppingcart-database.xml" />
</beans>


There are two different beans defined here, namely:
  • shoppingService – our shopping service class
  • jdbcTemplate – spring class used to simplify the use of JDBC

Next we will make changes to our ShoppingServiceTest class.

package com.mydomain.shoppingcart.service.test;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.LinkedList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mydomain.shoppingcart.bo.Basket;
import com.mydomain.shoppingcart.bo.BasketItem;
import com.mydomain.shoppingcart.bo.Item;
import com.mydomain.shoppingcart.dao.BasketDao;
import com.mydomain.shoppingcart.service.ShoppingService;

/**
* @author Ross
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/shoppingcart-test.xml" })
public class ShoppingServiceTest {
  private Basket basket;
  private BasketDao basketDaoMock;
  @Autowired
  private ShoppingService shoppingManager;
  private ShoppingService shoppingManagerMock;
  private Item testItem;

 /**
  * Tests adding an item to the basket.
  */
  @Test
  @DirtiesContext
  public void addItem() {
    int itemCount = basket.getItemCount();
    basket.addItem(testItem);
    assertEquals(itemCount + 1, basket.getItemCount());
  }

 /**
  * Tests emptying the basket.
  */
  @Test
  @DirtiesContext
  public void empty() {
    basket.empty();
    assertEquals(0, basket.getItemCount());
  }

 /**
  * Tests finding items.
  */
  @Test
  public void findItems() {
    try {
      int itemCount = basket.getItemCount();
      List<Item> mockResult = new LinkedList<Item>();
      for (int i = 0; i < itemCount; i++) {
        mockResult.add(new Item());
      }
      expect(shoppingManagerMock.findItems()).andReturn(mockResult);
      replay(shoppingManagerMock);

      List<Item> allItems = new LinkedList<Item>(shoppingManagerMock.findItems());
      assertEquals(itemCount, allItems.size());

      verify(shoppingManagerMock);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Error in Shopping Manager");
    }
  }

 /**
  * Tests removing an item from the cart.
  */
  @Test
  @DirtiesContext
  public void removeItem() {
    int itemCount = basket.getItemCount();
    for (BasketItem basketItem : basket.getBasketItems()) {
      basket.removeItem(basketItem.getItem());
      break;
    }
    assertEquals(itemCount - 1, basket.getItemCount());
  }

 /**
  * Tests saving a basket.
  */
  @Test
  public void saveBasket() {
    try {
      shoppingManager.setBasketDao(basketDaoMock);
      basketDaoMock.saveOrUpdateBasket(basket);
      replay(basketDaoMock);
      shoppingManager.updateBasket(basket);
      verify(basketDaoMock);
    } catch (Exception e) {
      e.printStackTrace();
      fail("Error in Shopping Manager");
    }
  }

 /**
  * Sets up the test fixture.
  *
  * Called before every test case method.
  */
  @Before
  public void setUp() {
    try {
      shoppingManagerMock = createMock(ShoppingService.class);
      basketDaoMock = createMock(BasketDao.class);
      testItem = new Item(1l, "Candy Cotton", "Candy coated milky tarts", 8.50d);
      basket = new Basket();
      basket.addItem(new Item(2l, "Jelly Beans", "Jelly icecream waffle cream", 18.99d));
      basket.addItem(new Item(3l, "Jam Doughnut", "Strawberry jam and Christmas pudding", 23.00d));
    } catch (Exception e) {
      e.printStackTrace();
      fail("Error setting up test case");
    }
  }
}

Ok there are a couple of things I would like to point out here and step through them each:
  • @RunWith attribute is a JUnit annotation and is used when you want to override the default JUnit runner. Here we want to use Springs own implementation in order to use Spring in our tests.
  • @ContextConfiguration is a Spring annotation and sets the location of the Spring bean configuration files needed for this test.
  • @Autowired is a Spring annotation that tells the compiler to automatically "wire" the variable (in this case shoppingManager) to the matching bean configured in the Spring bean configuration file.
  • Lastly we have our test method. Nothing really fancy about the body of the method. You notice we didn't have to create any objects or initialize anything as Spring did that for us. There is one more additional Spring annotation, @DirtiesContext. This annotation ensures that this method gets a clean context before it executes. Another test method may have altered the state of the beans defined in the Spring configuration files this annotation ensures the state of those beans will be the same as its original state before it executes.

Mock object test
Mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A mock object is created to test the behavior of some other object. Mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test. If an object has any of the following characteristics, it may be useful to use a mock object in its place:
  • Supplies non-deterministic results (e.g. the current time or the current temperature)
  • Has states that are difficult to create or reproduce (e.g. a network error)
  • Is slow (e.g. a complete database, which would have to be initialized before the test)
  • Does not yet exist or may change behavior
  • Would have to include information and methods exclusively for testing purposes (and not for its actual task)
  • Mock objects have the same interface as the real objects they mimic, allowing a client object to remain unaware of whether it is using a real object or a mock object.

EasyMock
EasyMock is a third party library that provides Mock Objects for interfaces in JUnit tests by generating them on the fly.

Shopping Cart Application
In the shopping cart application I created two different mock objects to show you how and where you can use them:
  • ShoppingManagerMock – A mock for the shopping service interface. You would most likely want to create a mock object for a service that you are looking up remotely and have no control over it. In the shopping cart application this is not the case but this example demonstrates what you can do.
  • BasketDaoMock – A mock for the basket dao. You may not want to test your service class but not the actual persistence of data to the database. Simply because there is a performance overhead setting up connections and persisting data to the database as well as managing the test data that you save and delete from the database. You don't want to corrupt your database with your tests. The last part of this tutorial shows you an example of testing your DAO's.

In our setup method we create the mock objects using EasyMocks createMock static method. This call creates a mock object that implements the given interface.

The first thing we do is define what method calls we expect should be made on our mock object. We can also define what result we expect back from a method call:

expect(shoppingManagerMock.findItems()).andReturn(mockResult); 

Once we have set up all our expectations (in our case only one) we change the mode of our mock test to replay. What this means is that every other method call made on our mock object from this point on will be checked to see if it is what we expect to be called.

replay(shoppingManagerMock); List<Item> allItems = new LinkedList<Item>(shoppingManagerMock.findItems()); assertEquals(itemCount, allItems.size());

Finally at the end of our test we call the EasyMock verify method that verifies the expected behaviour and throws an exception if it does not match.

verify(shoppingManagerMock); 

I created a new test method to test the BasketDao mock object. As you can see it is very similar to the above test. You will notice that I am not using the shopping manager mock object.

@Test
public void saveBasket() {
  try {
    shoppingManager.setBasketDao(basketDaoMock);
    basketDaoMock.saveOrUpdateBasket(basket);
    replay(basketDaoMock);
    shoppingManager.updateBasket(basket);
    verify(basketDaoMock);
  } catch (Exception e) {
    e.printStackTrace();
    fail("Error in Shopping Manager");
  }
}

Database Integration Tests
I would call this a type of integration test because we are testing the integration of our application with the database. I created a new test called BasketDaoTest to test the BasketDao data access class. These are the following steps I took when putting together this test:
  • Create test data that we will use to insert into our database and then remove at the end of the test
  • Create new test class to test the BasketDao class

1. Test data
We are going to create test data to run our tests against. You don’t want to run your test against data already in the database. For one you don’t know what data is there and two you don’t want to mess with someone else’s data. It is therefore essential to create our own data.
I created an xml file (shoppingcart-dbunit.xml) for my test data that will be used by DBUnit to insert into the database and at the end of the test remove it from the database. An example of the xml I used looks like the following:

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <basket ID="100001" />
  <item ID="100001" DESCRIPTION="Candy coated milky tarts" NAME="Candy Cotton" PRICE="8.5"/>
  <item ID="100002" DESCRIPTION="Jelly icecream waffle cream" NAME="Jelly Beans" PRICE="18.99"/>
  <basket_item ID="100001" BASKET_ID="100001" ITEMS_ID="100001" QUANTITY="2" PRICE="17"/>
  <basket_item ID="100002" BASKET_ID="100001" ITEMS_ID="100002" QUANTITY="1" PRICE="18.99"/>
</dataset>

DbUnit is a JUnit extension targeted at database-driven projects that puts your database into a known state between test runs. The easiest way to create this test data is to export the data from the database. There are specific DBUnit classes you can use to export data in the format required either by writing a java application that does it or by using an ant task made available by DBUnit to do this.


2. Test class
Now that we the data that our test is going to use we can move right along to our test class.
Once again we will leverage off Spring to make our lives a whole lot easier. If you take a look at our class declaration you will notice a couple of interesting points.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/shoppingcart-test.xml" })
@TransactionConfiguration
@Transactional
public class BasketDaoTest extends AbstractTransactionalJUnit4SpringContextTests {

This class is an abstract transactional extension of AbstractJUnit4SpringContextTests () which adds convenience functionality for JDBC access. It expects a DataSource bean and a PlatformTransactionManager bean to be defined in the Spring application context.

This class exposes a SimpleJdbcTemplate and provides an easy way to count the number of rows in a table, delete from the database , and execute SQL scripts within a transaction.

The @TransactionConfiguration and @Transactional annotations configure transactions for the tests.

I have broken our test class up into the following steps:
  1. Record current state of data in the database
  2. Insert test data into the database
  3. Run test on data in database
  4. Delete test data from database
  5. Validate data stored in the database to match original state

1. Record current state of data in the database
The first step I decided to do is to determine how many rows there are for the basket table. I did this so that at the end of the test I can compare the number of rows in the basket table to this value and check to see whether or not they are equal.

@BeforeTransaction
public void beforeTransaction() {
  basketTableRowCount = countRowsInTable(BASKET_TABLE_NAME);
}

The method with the annotation @BeforeTransaction is run before the transaction starts.

2. Insert test data into the database
I take the test data we created and I use DBUnit classes to insert the data into the database.

@Before
public void setUpTestDataWithinTransaction() {
  try {
    IDatabaseConnection connection = new DatabaseConnection(jdbcTemplate.getDataSource().getConnection());
    DatabaseOperation.INSERT.execute(connection, new FlatXmlDataSet(new FileInputStream(TEST_DATA_FILE)));
    jdbcTemplate.getDataSource().getConnection().close();
  } catch (Exception e) {
    e.printStackTrace();
  }
}

As we saw in the earlier tutorial on test cases the method with a @Before annotation gets called before any test methods.

3. Run test on data in database
All our JUnit test methods can now be run

@Test
@Rollback(true)
public void saveOrUpdateBasket() {
  assertNotNull("Basket DAO is null.", basketDao);
  try {
    Collection<Basket> baskets = basketDao.loadById(1);

    assertNotNull("Basket list is null.", baskets);
    assertEquals("Number of baskets should be " + basketTableRowCount + 1 + ".", basketTableRowCount + 1, baskets.size());

    for (Basket basket : baskets) {
      assertNotNull("Basket is null.", basket);
    }
  } catch (Exception e) {
    fail("Error in saveOrUpdateBasket");
  }
}

The @Test annotation identifies this method as our test method to run. The @Rollback annotation is a Spring test annotation used to indicate whether or not the transaction for the annotated test method should be rolled back after the test method has completed. If true, the transaction will be rolled back; otherwise, the transaction will be committed.

4. Delete test data from database
At the end of all our tests we use DBUnit again to delete our test data from the database so that the state of the database returns to what it was before the start of our test case.

@After
public void tearDownWithinTransaction() {
  try {
    IDatabaseConnection connection = new DatabaseConnection(jdbcTemplate.getDataSource().getConnection());
    DatabaseOperation.DELETE.execute(connection, new FlatXmlDataSet(new FileInputStream(TEST_DATA_FILE)));
    jdbcTemplate.getDataSource().getConnection().close();
  } catch (Exception e) {
    fail("Error in tearDownWithinTransaction");
  }
}

As we saw in the earlier tutorial on test cases the method with a @After annotation gets called after all the test methods have been called.

5. Validate data stored in the database to match original state
Here we validate the number of rows in our basket table to the number we originally retrieved at the start of our test.

@AfterTransaction
public void afterTransaction() {
  assertEquals(basketTableRowCount, countRowsInTable(BASKET_TABLE_NAME));
}

The method with the annotation @AfterTransaction is run after the transaction ends.