diff --git a/entity_js.info b/entity_js.info
index 64f9553..84a3a62 100644
--- a/entity_js.info
+++ b/entity_js.info
@@ -4,3 +4,4 @@ core = 7.x
 dependencies[] = entity
 dependencies[] = jquery_update
 scripts[] = entity.js
+files[] = entity_js.test
diff --git a/entity_js.test b/entity_js.test
new file mode 100644
index 0000000..65f7133
--- /dev/null
+++ b/entity_js.test
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Tests for entity_js.module.
+ */
+
+/**
+ * Tests for CRUD.
+ */
+class EntityJSTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Entity JS',
+      'description' => 'Test CRUD for Entity JS.',
+      'group' => 'Entity JS',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('entity_js');
+    // Create a user that is able to perform node CRUD functions.
+    $this->privileged_user = $this->drupalCreateUser(array(
+      'node entity js create',
+      'node entity js update',
+      'node entity js delete',
+      'node entity js read',
+      'access efq javascript callbacks',
+    ));
+
+    $this->drupalLogin($this->privileged_user);
+  }
+
+  /**
+   * Test CRUD using callbacks.
+   */
+  function testEntityJSCRUD() {
+    // Test entity_js_create.
+    $post = array('values' => array('title' => $this->randomName(8), 'type' => 'page'));
+    $this->drupalPostCallback('entity_js_create/node', $post);
+    // Check that the node exists in the database.
+    $node = $this->drupalGetNodeByTitle($post['values']["title"]);
+    $this->assertTrue($node, 'Node found in database.');
+
+    // Test entity_js_drupal_render_entity_view.
+    $this->drupalGet('entity_js_drupal_render_entity_view/node/' . $node->nid . '/default');
+    // Return is an HTML output. Simply check the title.
+    $this->assertText($node->title, 'Successfully viewed the node.');
+
+    // Test entity_js_load_single_json.
+    $output = $this->drupalGet('entity_js_load_single_json/node/' . $node->nid);
+    $this->assertEqual(drupal_json_decode($output), (array) $node, 'Successfully loaded the node.');
+
+    // Test entity_js_update.
+    $post = array('values' => array('title' => $this->randomName(8)));
+    $this->drupalPostCallback('entity_js_update/node/' . $node->nid, $post);
+    // Check that the node exists with the new title.
+    $node = $this->drupalGetNodeByTitle($post['values']['title']);
+    $this->assertTrue($node, 'Node with new title found in database.');
+
+    // Test entity_js_delete.
+    $this->drupalGet('entity_js_delete/node/' . $node->nid);
+    $node = node_load($node->nid, TRUE);
+    $this->assertFalse($node, 'Successfully deleted the node.');
+  }
+
+  /**
+   * Simple function similar to DrupalWebTestCase::drupalGet() but using POST as
+   * the method.
+   */
+  protected function drupalPostCallback($path, $post) {
+    $out = $this->curlExec(array(CURLOPT_URL => $this->getAbsoluteUrl($path), CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => drupal_http_build_query($post)));
+    $this->refreshVariables();
+
+    if ($new = $this->checkForMetaRefresh()) {
+      $out = $new;
+    }
+
+    $this->verbose('POST request to: ' . $path .
+      '<hr />Ending URL: ' . $this->getUrl() .
+      '<hr />Fields: ' . highlight_string('<?php ' . var_export($post, TRUE), TRUE) .
+      '<hr />' . $out);
+
+    return $out;
+  }
+}
