diff --git a/fivestar.info b/fivestar.info
index f4d802c..70783dd 100644
--- a/fivestar.info
+++ b/fivestar.info
@@ -6,3 +6,4 @@ dependencies[] = votingapi
 configure = admin/config/content/fivestar
 files[] = test/fivestar.base.test
 files[] = test/fivestar.field.test
+files[] = test/fivestar.microdata.test
diff --git a/test/fivestar.base.test b/test/fivestar.base.test
index fb95f3b..09657f9 100644
--- a/test/fivestar.base.test
+++ b/test/fivestar.base.test
@@ -14,10 +14,16 @@ class FivestarBaseTestCase extends AJAXTestCase {
   protected $voter;
   
   public function setUp() {
-    parent::setUp(array('fivestar', 'dblog'));
+    // Caller may have passed in modules to enable.
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    $modules = array_merge($modules, array('fivestar', 'dblog'));
+    parent::setUp($modules);
 
     $type = $this->drupalCreateContentType(array('type' => 'test_node_type', 'name' => 'test_node_type'));
-    $this->admin_user = $this->drupalCreateUser(array('create test_node_type content', 'rate content'));
+    $this->admin_user = $this->drupalCreateUser(array('create test_node_type content', 'edit any test_node_type content', 'rate content'));
     $this->voter_user = $this->drupalCreateUser(array('rate content'));
  }
 
diff --git a/test/fivestar.microdata.test b/test/fivestar.microdata.test
new file mode 100644
index 0000000..40dfca4
--- /dev/null
+++ b/test/fivestar.microdata.test
@@ -0,0 +1,135 @@
+<?php
+/**
+ * @file
+ * Simpletests for the Fivestar module's microdata integration.
+ */
+
+class FivestarMicrodataTestCase extends FivestarBaseTestCase {
+  protected $testDelegate;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Fivestar microdata',
+      'description' => 'Test placement of microdata.',
+      'group' => 'Fivestar',
+    );
+  }
+
+  /**
+   * Implements DrupalWebTestCase::setUp().
+   */
+  function setUp() {
+    parent::setUp(array('microdata'));
+    $this->testDelegate = new FivestarMicrodataTestDelegate();
+    // Save the mappings.
+    $mappings = $this->testDelegate->getMapping();
+    foreach ($mappings as $entity_type => $bundle_mappings) {
+      foreach ($bundle_mappings as $bundle_type => $mapping) {
+        microdata_save_mapping($entity_type, $bundle_type, $mapping);
+      }
+    }
+  }
+
+  /**
+   * Test the exposed widget.
+   */
+  public function testRateWhileViewing() {
+    // Add a viewer-rated fivestar field to the test_node_type content type.
+    $this->createFivestarField(array('widget_type' => 'exposed'));
+    // Add a node.
+    $node = $this->drupalCreateNode(array('type' => $this->testDelegate->bundleType, 'promote' => 1));
+    $this->drupalGet('node/' . $node->nid);
+    $this->drupalLogin($this->voter_user);
+
+    // Rate the test_node_type.
+    $edit = array(
+      'vote' => '40',
+    );
+    $this->drupalPost('node/' . $node->nid, $edit, t('Rate'));
+
+    // Run the actual tests on the microdata.
+    $this->subtestMicrodataValues();
+  }
+
+  /**
+   * Test the author widget.
+   */
+  public function testRateWhileEditing() {
+    $this->drupalLogin($this->admin_user);
+
+    // Add an author-rated fivestar field to the test_node_type content type.
+    $this->createFivestarField(array('widget_type' => 'stars'));
+
+    // Add a node.
+    $node = $this->drupalCreateNode(array('type' => $this->testDelegate->bundleType, 'promote' => 1));
+
+    // Save a two-star rating.
+    $edit = array(
+      'fivestar_test[und][0][rating]' => '40' // Equals a rating of 2 stars.
+    );
+    $this->drupalPost("node/{$node->nid}/edit", $edit, t('Save'));
+
+    // Run the actual tests on the microdata.
+    $this->subtestMicrodataValues();
+  }
+
+  protected function subtestMicrodataValues() {
+    $rating_value = '2';
+    $field_name = $this->testDelegate->fieldName;
+
+    // Get the mapping.
+    $full_mapping = $this->testDelegate->getMapping();
+    $mapping = $full_mapping['node'][$this->testDelegate->bundleType];
+
+    // Get the microdata result for the field.
+    $md = $this->testDelegate->parseMicrodata($this);
+    $itemprop = $mapping[$field_name]['#itemprop'][0];
+    $field_data = $md->items[0]->properties[$itemprop][0];
+
+    // Test itemtype.
+    $field_itemtype = $mapping[$field_name]['#itemtype'][0];
+    $this->assertEqual($field_itemtype, $field_data->type[0], 'Itemtype is placed on field.');
+
+    // Test average_rating property.
+    $avg_itemprop = $mapping[$field_name]['average_rating']['#itemprop'][0];
+    $this->assertEqual($rating_value, $field_data->properties[$avg_itemprop][0], 'Itemprop is placed on average rating property.');
+  }
+}
+
+class FivestarMicrodataTestDelegate extends MicrodataFieldTestCase {
+  public $bundleType = 'test_node_type';
+  public $fieldName = 'fivestar_test';
+
+  protected function getFields() {
+    return array();
+  }
+
+  protected function getInstances() {
+    return array();
+  }
+
+  public function getMapping() {
+    $mapping = array(
+      $this->entityType => array(
+        $this->bundleType => array(
+          '#itemtype' => array('http://schema.org/Recipe'),
+          // Title.
+          'title' => array(
+            '#itemprop' => array('name'),
+          ),
+          // Fivestar rating.
+          $this->fieldName => array(
+            '#itemprop' => array('aggregateRating'),
+            '#is_item' => TRUE,
+            '#itemtype' => array('http://schema.org/AggregateRating'),
+            'average_rating' => array(
+              '#itemprop' => array('ratingValue'),
+            ),
+          ),
+        ),
+      ),
+    );
+
+    return $mapping;
+  }
+}
