diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/CheckerBehaviors.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/CheckerBehaviors.scala
new file mode 100644
index 0000000000000000000000000000000000000000..84460d6579bd635e522d36d7db17c5acd29f258e
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/CheckerBehaviors.scala
@@ -0,0 +1,14 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+
+import net.i2p.update.Checker
+
+/**
+ * @author str4d
+ */
+trait CheckerBehaviors { this: FunSpec =>
+    def checker(newChecker: => Checker) {
+        it("should provide a method to check for updates") (pending)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/ConsoleUpdateManagerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/ConsoleUpdateManagerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..a4754c6c880112a689241da98b448952e90ba671
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/ConsoleUpdateManagerSpec.scala
@@ -0,0 +1,21 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class ConsoleUpdateManagerSpec extends FunSpec with UpdateManagerBehaviors with MockitoSugar {
+    def consoleUpdateManager = {
+        val mockCtx = mock[RouterContext]
+        val cum = new ConsoleUpdateManager(mockCtx)
+        cum
+    }
+
+    describe("A ConsoleUpdateManager") {
+        it should behave like updateManager(consoleUpdateManager)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/DummyHandlerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/DummyHandlerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..4124119294fc00a08b5ddb8cd287deb7ea0c3d93
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/DummyHandlerSpec.scala
@@ -0,0 +1,24 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class DummyHandlerSpec extends FunSpec with CheckerBehaviors with UpdaterBehaviors with MockitoSugar {
+    def dummyHandler = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val dh = new DummyHandler(mockCtx, mockMgr)
+        dh
+    }
+
+    describe("A DummyHandler") {
+        it should behave like checker(dummyHandler)
+
+        it should behave like updater(dummyHandler)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsFetcherSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsFetcherSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..b69bb7124554bffaaeecf2a7676174f91ea422ce
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsFetcherSpec.scala
@@ -0,0 +1,27 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import java.net.URI
+import java.util.Collections
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class NewsFetcherSpec extends FunSpec with UpdateRunnerBehaviors with MockitoSugar {
+    def newsFetcher = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val mockUri = mock[URI]
+        val uris = Collections.singletonList(mockUri)
+        val nf = new NewsFetcher(mockCtx, mockMgr, uris)
+        nf
+    }
+
+    describe("A NewsFetcher") {
+        it should behave like updateRunner(newsFetcher)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsHandlerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsHandlerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..03867b38c4b60cc192d0314a240f6fd186e626b8
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsHandlerSpec.scala
@@ -0,0 +1,22 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class NewsHandlerSpec extends FunSpec with UpdaterBehaviors with MockitoSugar {
+    def newsHandler = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val nh = new NewsHandler(mockCtx, mockMgr)
+        nh
+    }
+
+    describe("A NewsHandler") {
+        it should behave like updater(newsHandler)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsTimerTaskSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsTimerTaskSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..522a66131f632eafd1f250c86e81de0a21864a1c
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/NewsTimerTaskSpec.scala
@@ -0,0 +1,13 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+/**
+ * @author str4d
+ */
+class NewsTimerTaskSpec extends FunSpec with MockitoSugar {
+    describe("A NewsTimerTask") {
+        it("should keep track of time") (pending)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateCheckerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateCheckerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..33cb6707d7dfc4eed7bbddbad880ef1e89940706
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateCheckerSpec.scala
@@ -0,0 +1,27 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import java.net.URI
+import java.util.Collections
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class PluginUpdateCheckerSpec extends FunSpec with UpdateRunnerBehaviors with MockitoSugar {
+    def pluginUpdateChecker = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val mockUri = mock[URI]
+        val uris = Collections.singletonList(mockUri)
+        val puc = new PluginUpdateChecker(mockCtx, mockMgr, uris, "appName", "appVersion")
+        puc
+    }
+
+    describe("A PluginUpdateChecker") {
+        it should behave like updateRunner(pluginUpdateChecker)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateHandlerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateHandlerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..279a0ce5f517a81b09cda043a2976414df137926
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateHandlerSpec.scala
@@ -0,0 +1,24 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class PluginUpdateHandlerSpec extends FunSpec with CheckerBehaviors with UpdaterBehaviors with MockitoSugar {
+    def pluginUpdateHandler = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val puh = new PluginUpdateHandler(mockCtx, mockMgr)
+        puh
+    }
+
+    describe("A PluginUpdateHandler") {
+        it should behave like checker(pluginUpdateHandler)
+
+        it should behave like updater(pluginUpdateHandler)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateRunnerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateRunnerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c5ee14dc506aed45eb6674b6ace1373d1136cdf6
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/PluginUpdateRunnerSpec.scala
@@ -0,0 +1,27 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import java.net.URI
+import java.util.Collections
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class PluginUpdateRunnerSpec extends FunSpec with UpdateRunnerBehaviors with MockitoSugar {
+    def pluginUpdateRunner = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val mockUri = mock[URI]
+        val uris = Collections.singletonList(mockUri)
+        val pur = new PluginUpdateRunner(mockCtx, mockMgr, uris, "appName", "appVersion")
+        pur
+    }
+
+    describe("A PluginUpdateRunner") {
+        it should behave like updateRunner(pluginUpdateRunner)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateCheckerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateCheckerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..63d0c3f97e941d7763ba76f1e9c8f8497869ed65
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateCheckerSpec.scala
@@ -0,0 +1,27 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import java.net.URI
+import java.util.Collections
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class UnsignedUpdateCheckerSpec extends FunSpec with UpdateRunnerBehaviors with MockitoSugar {
+    def unsignedUpdateChecker = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val mockUri = mock[URI]
+        val uris = Collections.singletonList(mockUri)
+        val uuc = new UnsignedUpdateChecker(mockCtx, mockMgr, uris, 0)
+        uuc
+    }
+
+    describe("An UnsignedUpdateChecker") {
+        it should behave like updateRunner(unsignedUpdateChecker)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateHandlerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateHandlerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..802ade31c7068567a09256ad4227544e321b0d2a
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateHandlerSpec.scala
@@ -0,0 +1,24 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class UnsignedUpdateHandlerSpec extends FunSpec with CheckerBehaviors with UpdaterBehaviors with MockitoSugar {
+    def unsignedUpdateHandler = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val uuh = new UnsignedUpdateHandler(mockCtx, mockMgr)
+        uuh
+    }
+
+    describe("An UnsignedUpdateHandler") {
+        it should behave like checker(unsignedUpdateHandler)
+
+        it should behave like updater(unsignedUpdateHandler)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateRunnerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateRunnerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..d400215b078f448ecc692766cccc42054da46679
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UnsignedUpdateRunnerSpec.scala
@@ -0,0 +1,27 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import java.net.URI
+import java.util.Collections
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class UnsignedUpdateRunnerSpec extends FunSpec with UpdateRunnerBehaviors with MockitoSugar {
+    def unsignedUpdateRunner = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val mockUri = mock[URI]
+        val uris = Collections.singletonList(mockUri)
+        val uur = new UnsignedUpdateRunner(mockCtx, mockMgr, uris)
+        uur
+    }
+
+    describe("An UnsignedUpdateRunner") {
+        it should behave like updateRunner(unsignedUpdateRunner)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateHandlerSpec.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateHandlerSpec.scala
new file mode 100644
index 0000000000000000000000000000000000000000..2b533813af536fe9b601dac75d658a305e8f14a9
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateHandlerSpec.scala
@@ -0,0 +1,22 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+import org.scalatest.mock.MockitoSugar
+
+import net.i2p.router.RouterContext
+
+/**
+ * @author str4d
+ */
+class UpdateHandlerSpec extends FunSpec with UpdaterBehaviors with MockitoSugar {
+    def updateHandler = {
+        val mockCtx = mock[RouterContext]
+        val mockMgr = mock[ConsoleUpdateManager]
+        val uh = new UpdateHandler(mockCtx, mockMgr)
+        uh
+    }
+
+    describe("An UpdateHandler") {
+        it should behave like updater(updateHandler)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateManagerBehaviors.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateManagerBehaviors.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ba7835a1bfdfd976b6ad55a2da509dd95ef9dc81
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateManagerBehaviors.scala
@@ -0,0 +1,40 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+
+import net.i2p.update.UpdateManager
+
+/**
+ * @author str4d
+ */
+trait UpdateManagerBehaviors { this: FunSpec =>
+    def updateManager(newUpdateManager: => UpdateManager) {
+        it("should provide a method to register updaters") (pending)
+
+        it("should provide a method to unregister updaters") (pending)
+
+        it("should provide a method to register checkers") (pending)
+
+        it("should provide a method to unregister checkers") (pending)
+
+        it("should provide a start method") (pending)
+
+        it("should provide a shutdown method") (pending)
+
+        it("should notify when a new version is available") (pending)
+
+        it("should notify when a check is complete") (pending)
+
+        it("should provide a method to notify progress") (pending)
+
+        it("should provide a method to notify progress with completion status") (pending)
+
+        it("should notify when a single update attempt fails") (pending)
+
+        it("should notify when an entire task finishes and has failed") (pending)
+
+        it("should notify when an update has been downloaded, and verify it") (pending)
+
+        it("should notify when") (pending)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateRunnerBehaviors.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateRunnerBehaviors.scala
new file mode 100644
index 0000000000000000000000000000000000000000..c88e9bab32478c6e7b8a64dc44755f16cda2f730
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdateRunnerBehaviors.scala
@@ -0,0 +1,12 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+
+/**
+ * @author str4d
+ */
+trait UpdateRunnerBehaviors { this: FunSpec =>
+    def updateRunner(newUpdateRunner: => UpdateRunner) {
+        it("should provide a method to run updates") (pending)
+    }
+}
diff --git a/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdaterBehaviors.scala b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdaterBehaviors.scala
new file mode 100644
index 0000000000000000000000000000000000000000..558983497d412f796b347a45218f1cb0695b2d57
--- /dev/null
+++ b/apps/routerconsole/java/test/scalatest/net/i2p/router/update/UpdaterBehaviors.scala
@@ -0,0 +1,14 @@
+package net.i2p.router.update
+
+import org.scalatest.FunSpec
+
+import net.i2p.update.Updater
+
+/**
+ * @author str4d
+ */
+trait UpdaterBehaviors { this: FunSpec =>
+    def updater(newUpdater: => Updater) {
+        it("should provide a method to perform updates") (pending)
+    }
+}