diff --git a/jdbc/pom.xml b/jdbc/pom.xml
index bf80e1824d662f7cadc1305f8b3f6f1a9d6e7d43..80bfc20c1840ba5ce124353f7de97a7978bac7f9 100644
--- a/jdbc/pom.xml
+++ b/jdbc/pom.xml
@@ -41,5 +41,17 @@ LICENSE file.
       <version>${project.version}</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.hsqldb</groupId>
+      <artifactId>hsqldb</artifactId>
+      <version>2.3.3</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/jdbc/src/test/java/com/yahoo/ycsb/db/JdbcDBClientTest.java b/jdbc/src/test/java/com/yahoo/ycsb/db/JdbcDBClientTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..901c8a668a035a8130a9070d044664736fc994ca
--- /dev/null
+++ b/jdbc/src/test/java/com/yahoo/ycsb/db/JdbcDBClientTest.java
@@ -0,0 +1,335 @@
+/**
+ * Copyright (c) 2015 Yahoo! Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License. See accompanying
+ * LICENSE file.
+ */
+
+package com.yahoo.ycsb.db;
+
+import static org.junit.Assert.*;
+
+import com.yahoo.ycsb.ByteIterator;
+import com.yahoo.ycsb.DBException;
+import com.yahoo.ycsb.StringByteIterator;
+import org.junit.*;
+
+import java.sql.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * Created by kruthar on 11/2/15.
+ */
+public class JdbcDBClientTest {
+    private static final String TEST_DB_DRIVER = "org.hsqldb.jdbc.JDBCDriver";
+    private static final String TEST_DB_URL = "jdbc:hsqldb:mem:ycsb";
+    private static final String TEST_DB_USER = "sa";
+    private static final String TABLE_NAME = "USERTABLE";
+    private static final int FIELD_LENGTH = 32;
+    private static final String FIELD_PREFIX = "FIELD";
+    private static final String KEY_PREFIX = "user";
+    private static final String KEY_FIELD = "YCSB_KEY";
+    private static final int NUM_FIELDS = 3;
+
+    private static Connection jdbcConnection = null;
+    private static JdbcDBClient jdbcDBClient = null;
+
+    @BeforeClass
+    public static void setup() {
+        try {
+            jdbcConnection = DriverManager.getConnection(TEST_DB_URL);
+            jdbcDBClient = new JdbcDBClient();
+
+            Properties p = new Properties();
+            p.setProperty(JdbcDBClientConstants.CONNECTION_URL, TEST_DB_URL);
+            p.setProperty(JdbcDBClientConstants.DRIVER_CLASS, TEST_DB_DRIVER);
+            p.setProperty(JdbcDBClientConstants.CONNECTION_USER, TEST_DB_USER);
+
+            jdbcDBClient.setProperties(p);
+            jdbcDBClient.init();
+        } catch (SQLException e) {
+            e.printStackTrace();
+            fail("Could not create local Database");
+        } catch (DBException e) {
+            e.printStackTrace();
+            fail("Could not create JdbcDBClient instance");
+        }
+    }
+
+    @AfterClass
+    public static void teardown() {
+        try {
+            if (jdbcConnection != null) {
+                jdbcConnection.close();
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        
+        try {
+            if (jdbcDBClient != null) {
+                jdbcDBClient.cleanup();
+            }
+        } catch (DBException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Before
+    public void prepareTest() {
+        try {
+            DatabaseMetaData metaData = jdbcConnection.getMetaData();
+            ResultSet tableResults = metaData.getTables(null, null, TABLE_NAME, null);
+            if (tableResults.next()) {
+                // If the table already exists, just truncate it
+                jdbcConnection.prepareStatement(
+                    String.format("TRUNCATE TABLE %s", TABLE_NAME)
+                ).execute();
+            } else {
+                // If the table does not exist then create it
+                StringBuilder createString = new StringBuilder(
+                    String.format("CREATE TABLE %s (%s VARCHAR(100) PRIMARY KEY", TABLE_NAME, KEY_FIELD)
+                );
+                for (int i = 0; i < NUM_FIELDS; i++) {
+                    createString.append(
+                        String.format(", %s%d VARCHAR(100)", FIELD_PREFIX, i)
+                    );
+                }
+                createString.append(")");
+                jdbcConnection.prepareStatement(createString.toString()).execute();
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+            fail("Failed to prepare test");
+        }
+    }
+
+    /*
+        This is a copy of buildDeterministicValue() from core:com.yahoo.ycsb.workloads.CoreWorkload.java.
+        That method is neither public nor static so we need a copy.
+     */
+    private String buildDeterministicValue(String key, String fieldkey) {
+        int size = FIELD_LENGTH;
+        StringBuilder sb = new StringBuilder(size);
+        sb.append(key);
+        sb.append(':');
+        sb.append(fieldkey);
+        while (sb.length() < size) {
+            sb.append(':');
+            sb.append(sb.toString().hashCode());
+        }
+        sb.setLength(size);
+
+        return sb.toString();
+    }
+
+    /*
+        Inserts a row of deterministic values for the given insertKey using the jdbcDBClient.
+     */
+    private HashMap<String, ByteIterator> insertRow(String insertKey) {
+        HashMap<String, ByteIterator> insertMap = new HashMap<String, ByteIterator>();
+        for (int i = 0; i < 3; i++) {
+            insertMap.put(FIELD_PREFIX + i, new StringByteIterator(buildDeterministicValue(insertKey, FIELD_PREFIX + i)));
+        }
+        jdbcDBClient.insert(TABLE_NAME, insertKey, insertMap);
+
+        return insertMap;
+    }
+
+    @Test
+    public void insertTest() {
+        try {
+            String insertKey = "user0";
+            HashMap<String, ByteIterator> insertMap = insertRow(insertKey);
+
+            ResultSet resultSet = jdbcConnection.prepareStatement(
+                String.format("SELECT * FROM %s", TABLE_NAME)
+            ).executeQuery();
+
+            // Check we have a result Row
+            assertTrue(resultSet.next());
+            // Check that all the columns have expected values
+            assertEquals(resultSet.getString(KEY_FIELD), insertKey);
+            for (int i = 0; i < 3; i++) {
+                // TODO: This will fail until the fix is made to insert and update fields in the correct order.
+                // TODO: Uncomment this assertEquals when the fix is made.
+                //assertEquals(resultSet.getString(FIELD_PREFIX + i), insertMap.get(FIELD_PREFIX + i));
+            }
+            // Check that we do not have any more rows
+            assertFalse(resultSet.next());
+
+            resultSet.close();
+        } catch (SQLException e) {
+            e.printStackTrace();
+            fail("Failed insertTest");
+        }
+    }
+
+    @Test
+    public void updateTest() {
+        try {
+            String preupdateString = "preupdate";
+            StringBuilder fauxInsertString = new StringBuilder(
+                String.format("INSERT INTO %s VALUES(?", TABLE_NAME)
+            );
+            for (int i = 0; i < NUM_FIELDS; i++) {
+                fauxInsertString.append(",?");
+            }
+            fauxInsertString.append(")");
+
+            PreparedStatement fauxInsertStatement = jdbcConnection.prepareStatement(fauxInsertString.toString());
+            for (int i = 2; i < NUM_FIELDS + 2; i++) {
+                fauxInsertStatement.setString(i, preupdateString);
+            }
+
+            fauxInsertStatement.setString(1, "user0");
+            fauxInsertStatement.execute();
+            fauxInsertStatement.setString(1, "user1");
+            fauxInsertStatement.execute();
+            fauxInsertStatement.setString(1, "user2");
+            fauxInsertStatement.execute();
+
+            HashMap<String, ByteIterator> updateMap = new HashMap<String, ByteIterator>();
+            for (int i = 0; i < 3; i++) {
+                updateMap.put(FIELD_PREFIX + i, new StringByteIterator(buildDeterministicValue("user1", FIELD_PREFIX + i)));
+            }
+
+            jdbcDBClient.update(TABLE_NAME, "user1", updateMap);
+
+            ResultSet resultSet = jdbcConnection.prepareStatement(
+                String.format("SELECT * FROM %s ORDER BY %s", TABLE_NAME, KEY_FIELD)
+            ).executeQuery();
+
+            // Ensure that user0 record was not changed
+            resultSet.next();
+            assertEquals("Assert first row key is user0", resultSet.getString(KEY_FIELD), "user0");
+            for (int i = 0; i < 3; i++) {
+                assertEquals("Assert first row fields contain preupdateString", resultSet.getString(FIELD_PREFIX + i), preupdateString);
+            }
+
+            // Check that all the columns have expected values for user1 record
+            resultSet.next();
+            assertEquals(resultSet.getString(KEY_FIELD), "user1");
+            for (int i = 0; i < 3; i++) {
+                // TODO: This will fail until the fix is made to insert and update fields in the correct order.
+                // TODO: Uncomment this assertEquals when the fix is made.
+                //assertEquals(resultSet.getString(FIELD_PREFIX + i), updateMap.get(FIELD_PREFIX + i));
+            }
+
+            // Ensure that user2 record was not changed
+            resultSet.next();
+            assertEquals("Assert third row key is user2", resultSet.getString(KEY_FIELD), "user2");
+            for (int i = 0; i < 3; i++) {
+                assertEquals("Assert third row fields contain preupdateString", resultSet.getString(FIELD_PREFIX + i), preupdateString);
+            }
+            resultSet.close();
+        } catch (SQLException e) {
+            e.printStackTrace();
+            fail("Failed updateTest");
+        }
+    }
+
+    @Test
+    public void readTest() {
+        String insertKey = "user0";
+        HashMap<String, ByteIterator> insertMap = insertRow(insertKey);
+        HashSet<String> readFields = new HashSet<String>();
+        HashMap<String, ByteIterator> readResultMap = new HashMap<String, ByteIterator>();
+
+        // Test reading a single field
+        readFields.add("FIELD0");
+        jdbcDBClient.read(TABLE_NAME, insertKey, readFields, readResultMap);
+        assertEquals("Assert that result has correct number of fields", readFields.size(), readResultMap.size());
+        for (String field: readFields) {
+            // TODO: This will fail until the fix is made to insert and update fields in the correct order.
+            // TODO: Uncomment this assertEquals when the fix is made.
+            //assertEquals("Assert " + field + " was read correctly", insertMap.get(field), readResultMap.get(field));
+        }
+
+        readResultMap = new HashMap<String, ByteIterator>();
+
+        // Test reading all fields
+        readFields.add("FIELD1");
+        readFields.add("FIELD2");
+        jdbcDBClient.read(TABLE_NAME, insertKey, readFields, readResultMap);
+        assertEquals("Assert that result has correct number of fields", readFields.size(), readResultMap.size());
+        for (String field: readFields) {
+            // TODO: This will fail until the fix is made to insert and update fields in the correct order.
+            // TODO: Uncomment this assertEquals when the fix is made.
+            //assertEquals("Assert " + field + " was read correctly", insertMap.get(field), readResultMap.get(field));
+        }
+    }
+
+    @Test
+    public void deleteTest() {
+        try {
+            insertRow("user0");
+            String deleteKey = "user1";
+            insertRow(deleteKey);
+            insertRow("user2");
+
+            jdbcDBClient.delete(TABLE_NAME, deleteKey);
+
+            ResultSet resultSet = jdbcConnection.prepareStatement(
+                String.format("SELECT * FROM %s", TABLE_NAME)
+            ).executeQuery();
+
+            int totalRows = 0;
+            while (resultSet.next()) {
+                assertNotEquals("Assert this is not the deleted row key", deleteKey, resultSet.getString(KEY_FIELD));
+                totalRows++;
+            }
+            // Check we do not have a result Row
+            assertEquals("Assert we ended with the correct number of rows", totalRows, 2);
+
+            resultSet.close();
+        } catch (SQLException e) {
+            e.printStackTrace();
+            fail("Failed deleteTest");
+        }
+    }
+
+    @Test
+    public void scanTest() throws SQLException {
+        HashMap<String, HashMap<String, ByteIterator>> keyMap = new HashMap<String, HashMap<String, ByteIterator>>();
+        for (int i = 0; i < 5; i++) {
+            String insertKey = KEY_PREFIX + i;
+            keyMap.put(insertKey, insertRow(insertKey));
+        }
+        HashSet<String> fieldSet = new HashSet<String>();
+        fieldSet.add("FIELD0");
+        fieldSet.add("FIELD1");
+        int startIndex = 1;
+        int resultRows = 3;
+
+        Vector<HashMap<String, ByteIterator>> resultVector = new Vector<HashMap<String, ByteIterator>>();
+        jdbcDBClient.scan(TABLE_NAME, KEY_PREFIX + startIndex, resultRows, fieldSet, resultVector);
+
+        // Check the resultVector is the correct size
+        assertEquals("Assert the correct number of results rows were returned", resultRows, resultVector.size());
+        // Check each vector row to make sure we have the correct fields
+        int testIndex = startIndex;
+        for (HashMap<String, ByteIterator> result: resultVector) {
+            assertEquals("Assert that this row has the correct number of fields", fieldSet.size(), result.size());
+            for (String field: fieldSet) {
+                // TODO: This will fail until the fix is made to insert and update fields in the correct order.
+                // TODO: Uncomment this assertEquals when the fix is made.
+                //assertEquals("Assert this field is correct in this row", keyMap.get(KEY_PREFIX + testIndex).get(field), result.get(field));
+            }
+            testIndex++;
+        }
+    }
+}