diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxApiTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxApiTest.java
index 3b46320c8830c0845f2f3b087a06c3e6fee2a1d8..aeaaccbafd5a4da7f394aa0cc314f846d5d4ba1c 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxApiTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxApiTest.java
@@ -24,9 +24,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import javax.annotation.Nonnull;
-import javax.net.SocketFactory;
-
 import okhttp3.OkHttpClient;
 import okhttp3.mockwebserver.MockResponse;
 import okhttp3.mockwebserver.MockWebServer;
@@ -34,8 +31,8 @@ import okhttp3.mockwebserver.RecordedRequest;
 import okio.Buffer;
 
 import static java.util.Collections.singletonList;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
+import static org.briarproject.bramble.mailbox.MailboxTestUtils.createHttpClientProvider;
 import static org.briarproject.bramble.test.TestUtils.getContactId;
 import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
@@ -56,18 +53,8 @@ public class MailboxApiTest extends BrambleTestCase {
 	@Rule
 	public TemporaryFolder folder = new TemporaryFolder();
 
-	private final OkHttpClient client = new OkHttpClient.Builder()
-			.socketFactory(SocketFactory.getDefault())
-			.connectTimeout(60_000, MILLISECONDS)
-			.build();
 	private final WeakSingletonProvider<OkHttpClient> httpClientProvider =
-			new WeakSingletonProvider<OkHttpClient>() {
-				@Override
-				@Nonnull
-				public OkHttpClient createInstance() {
-					return client;
-				}
-			};
+			createHttpClientProvider();
 	// We aren't using a real onion address, so use the given address verbatim
 	private final UrlConverter urlConverter = onion -> onion;
 	private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider,
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java
index 6a3e312ed1716865dccdd71a40cd0f86b9ef3c98..fbc817d3f7f86882f69bd0106f6f3b5593ac2326 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxPairingTaskImplTest.java
@@ -22,13 +22,12 @@ import org.jmock.Expectations;
 import org.junit.Test;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import static java.util.Collections.singletonList;
+import static org.briarproject.bramble.mailbox.MailboxTestUtils.getQrCodePayload;
 import static org.briarproject.bramble.test.TestUtils.getContact;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
@@ -59,7 +58,8 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
 			new MailboxAuthToken(getRandomId());
 	private final MailboxAuthToken ownerToken =
 			new MailboxAuthToken(getRandomId());
-	private final String validPayload = getValidPayload();
+	private final String validPayload =
+			getQrCodePayload(onionBytes, setupToken.getBytes());
 	private final long time = System.currentTimeMillis();
 	private final MailboxProperties setupProperties = new MailboxProperties(
 			onion, setupToken, new ArrayList<>());
@@ -194,16 +194,6 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
 				MailboxPairingState.UnexpectedError.class));
 	}
 
-	private String getValidPayload() {
-		byte[] payloadBytes = ByteBuffer.allocate(65)
-				.put((byte) 32) // 1
-				.put(onionBytes) // 32
-				.put(setupToken.getBytes()) // 32
-				.array();
-		//noinspection CharsetObjectCanBeUsed
-		return new String(payloadBytes, Charset.forName("ISO-8859-1"));
-	}
-
 	private PredicateMatcher<MailboxProperties> matches(MailboxProperties p2) {
 		return new PredicateMatcher<>(MailboxProperties.class, p1 ->
 				p1.getAuthToken().equals(p2.getAuthToken()) &&
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxTestUtils.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxTestUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..4795fb739b5f484fc88e29a286b79bdd4355debf
--- /dev/null
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxTestUtils.java
@@ -0,0 +1,44 @@
+package org.briarproject.bramble.mailbox;
+
+import org.briarproject.bramble.api.WeakSingletonProvider;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+import javax.annotation.Nonnull;
+import javax.net.SocketFactory;
+
+import okhttp3.OkHttpClient;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.briarproject.bramble.test.TestUtils.getRandomId;
+
+class MailboxTestUtils {
+
+	static String getQrCodePayload(byte[] onionBytes, byte[] setupToken) {
+		byte[] payloadBytes = ByteBuffer.allocate(65)
+				.put((byte) 32) // 1
+				.put(onionBytes) // 32
+				.put(setupToken) // 32
+				.array();
+		//noinspection CharsetObjectCanBeUsed
+		return new String(payloadBytes, Charset.forName("ISO-8859-1"));
+	}
+
+	static String getQrCodePayload(byte[] setupToken) {
+		return getQrCodePayload(getRandomId(), setupToken);
+	}
+
+	static WeakSingletonProvider<OkHttpClient> createHttpClientProvider() {
+		return new WeakSingletonProvider<OkHttpClient>() {
+			@Override
+			@Nonnull
+			public OkHttpClient createInstance() {
+				return new OkHttpClient.Builder()
+						.socketFactory(SocketFactory.getDefault())
+						.connectTimeout(60_000, MILLISECONDS)
+						.build();
+			}
+		};
+	}
+}
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/AbstractMailboxIntegrationTest.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/AbstractMailboxIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f38f7910d55aac195f838437fe486280dfee9733
--- /dev/null
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/AbstractMailboxIntegrationTest.java
@@ -0,0 +1,84 @@
+package org.briarproject.bramble.mailbox;
+
+import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
+import org.briarproject.bramble.api.identity.Identity;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
+import org.briarproject.bramble.api.mailbox.MailboxPairingState;
+import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
+import org.briarproject.bramble.api.mailbox.MailboxProperties;
+import org.briarproject.bramble.test.BrambleTestCase;
+import org.briarproject.bramble.test.TestDatabaseConfigModule;
+import org.briarproject.mailbox.lib.AbstractMailbox;
+
+import java.io.File;
+import java.util.concurrent.CountDownLatch;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.briarproject.bramble.api.mailbox.MailboxAuthToken.fromString;
+import static org.briarproject.bramble.mailbox.MailboxTestUtils.getQrCodePayload;
+import static org.briarproject.bramble.test.TestUtils.getSecretKey;
+import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
+import static org.junit.Assert.fail;
+
+abstract class AbstractMailboxIntegrationTest extends BrambleTestCase {
+
+	static final String URL_BASE = "http://127.0.0.1:8000";
+
+	private final File testDir = getTestDirectory();
+	final File dir1 = new File(testDir, "alice");
+	final File dir2 = new File(testDir, "bob");
+
+	MailboxIntegrationTestComponent c1, c2;
+
+	MailboxIntegrationTestComponent startTestComponent(
+			File databaseDir, String name) throws Exception {
+		MailboxIntegrationTestComponent component =
+				DaggerMailboxIntegrationTestComponent
+						.builder()
+						.testDatabaseConfigModule(
+								new TestDatabaseConfigModule(databaseDir))
+						.build();
+		BrambleCoreIntegrationTestEagerSingletons.Helper
+				.injectEagerSingletons(component);
+		setUp(component, name);
+		return component;
+	}
+
+	private void setUp(MailboxIntegrationTestComponent device,
+			String name) throws Exception {
+		// Add an identity for the user
+		IdentityManager identityManager = device.getIdentityManager();
+		Identity identity = identityManager.createIdentity(name);
+		identityManager.registerIdentity(identity);
+		// Start the lifecycle manager
+		LifecycleManager lifecycleManager = device.getLifecycleManager();
+		lifecycleManager.startServices(getSecretKey());
+		lifecycleManager.waitForStartup();
+	}
+
+	MailboxProperties pair(MailboxIntegrationTestComponent c,
+			AbstractMailbox mailbox) throws Exception {
+		MailboxAuthToken setupToken = fromString(mailbox.getSetupToken());
+
+		MailboxPairingTask pairingTask = c.getMailboxManager()
+				.startPairingTask(getQrCodePayload(setupToken.getBytes()));
+
+		CountDownLatch latch = new CountDownLatch(1);
+		pairingTask.addObserver((state) -> {
+			if (state instanceof MailboxPairingState.Paired) {
+				latch.countDown();
+			}
+		});
+		if (!latch.await(10, SECONDS)) {
+			fail("Timeout reached when waiting for pairing.");
+		}
+		return c.getDatabaseComponent()
+				.transactionWithNullableResult(true, txn ->
+						c.getMailboxSettingsManager()
+								.getOwnMailboxProperties(txn)
+				);
+	}
+
+}
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxApiIntegrationTest.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxApiIntegrationTest.java
index e6ab681216f9f8cbdbcb0d59435953363c776701..d196d180dcff07c8af9e5f836bf26bf881e01263 100644
--- a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxApiIntegrationTest.java
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxApiIntegrationTest.java
@@ -26,7 +26,7 @@ import java.util.List;
 
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
-import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.URL_BASE;
+import static org.briarproject.bramble.mailbox.AbstractMailboxIntegrationTest.URL_BASE;
 import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestComponent.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestComponent.java
index a4fc1adb57bc559f8e0c3eca12e291964bc03743..aa37adc8bf97098bfd187ce4fa6713c11fc8b733 100644
--- a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestComponent.java
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestComponent.java
@@ -2,15 +2,11 @@ package org.briarproject.bramble.mailbox;
 
 import org.briarproject.bramble.BrambleCoreModule;
 import org.briarproject.bramble.api.contact.ContactManager;
-import org.briarproject.bramble.api.crypto.CryptoComponent;
 import org.briarproject.bramble.api.db.DatabaseComponent;
 import org.briarproject.bramble.api.identity.AuthorFactory;
 import org.briarproject.bramble.api.lifecycle.LifecycleManager;
 import org.briarproject.bramble.api.mailbox.MailboxManager;
 import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
-import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
-import org.briarproject.bramble.api.properties.TransportPropertyManager;
-import org.briarproject.bramble.api.system.Clock;
 import org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.TestUrlConverterModule;
 import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
 import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
@@ -38,19 +34,11 @@ interface MailboxIntegrationTestComponent extends
 
 	MailboxManager getMailboxManager();
 
-	MailboxUpdateManager getMailboxUpdateManager();
-
 	MailboxSettingsManager getMailboxSettingsManager();
 
 	LifecycleManager getLifecycleManager();
 
 	ContactManager getContactManager();
 
-	Clock getClock();
-
-	TransportPropertyManager getTransportPropertyManager();
-
 	AuthorFactory getAuthorFactory();
-
-	CryptoComponent getCrypto();
 }
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestUtils.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestUtils.java
index 3f27c648dc0bb703be017fc5a1b34a720c8c981a..9fd708fcda03d73cbd123a477a8e6d53c1be645b 100644
--- a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestUtils.java
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/MailboxIntegrationTestUtils.java
@@ -1,89 +1,16 @@
 package org.briarproject.bramble.mailbox;
 
-import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
-import org.briarproject.bramble.api.WeakSingletonProvider;
-import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
-import org.briarproject.bramble.test.TestDatabaseConfigModule;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import javax.annotation.Nonnull;
-import javax.net.SocketFactory;
-
-import dagger.Module;
-import dagger.Provides;
-import okhttp3.OkHttpClient;
-
 import static java.lang.System.currentTimeMillis;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.briarproject.bramble.mailbox.MailboxTestUtils.createHttpClientProvider;
+import static org.briarproject.bramble.mailbox.TestUrlConverterModule.urlConverter;
 import static org.junit.Assert.fail;
 
 class MailboxIntegrationTestUtils {
 
-	static final String URL_BASE = "http://127.0.0.1:8000";
-
-	static String getQrCodePayload(MailboxAuthToken setupToken) {
-		byte[] bytes = getQrCodeBytes(setupToken);
-		Charset charset = Charset.forName("ISO-8859-1");
-		return new String(bytes, charset);
-	}
-
-	private static byte[] getQrCodeBytes(MailboxAuthToken setupToken) {
-		byte[] hiddenServiceBytes = getHiddenServiceBytes();
-		byte[] setupTokenBytes = setupToken.getBytes();
-		return ByteBuffer.allocate(65).put((byte) 32)
-				.put(hiddenServiceBytes).put(setupTokenBytes).array();
-	}
-
-	private static byte[] getHiddenServiceBytes() {
-		byte[] data = new byte[32];
-		Arrays.fill(data, (byte) 'a');
-		return data;
-	}
-
-	private static WeakSingletonProvider<OkHttpClient> createHttpClientProvider() {
-		OkHttpClient client = new OkHttpClient.Builder()
-				.socketFactory(SocketFactory.getDefault())
-				.connectTimeout(60_000, MILLISECONDS)
-				.build();
-		return new WeakSingletonProvider<OkHttpClient>() {
-			@Override
-			@Nonnull
-			public OkHttpClient createInstance() {
-				return client;
-			}
-		};
-	}
-
 	static MailboxApi createMailboxApi() {
-		return new MailboxApiImpl(createHttpClientProvider(),
-				new TestUrlConverter());
-	}
-
-	static MailboxIntegrationTestComponent createTestComponent(
-			File databaseDir) {
-		MailboxIntegrationTestComponent component =
-				DaggerMailboxIntegrationTestComponent
-						.builder()
-						.testDatabaseConfigModule(
-								new TestDatabaseConfigModule(databaseDir))
-						.build();
-		BrambleCoreIntegrationTestEagerSingletons.Helper
-				.injectEagerSingletons(component);
-		return component;
-	}
-
-	@Module
-	static class TestUrlConverterModule {
-
-		@Provides
-		UrlConverter provideUrlConverter() {
-			return new TestUrlConverter();
-		}
+		return new MailboxApiImpl(createHttpClientProvider(), urlConverter);
 	}
 
 	interface Check {
@@ -126,6 +53,7 @@ class MailboxIntegrationTestUtils {
 				return;
 			}
 			try {
+				//noinspection BusyWait
 				Thread.sleep(step);
 			} catch (InterruptedException ignore) {
 				// continue
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/OwnMailboxContactListWorkerIntegrationTest.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/OwnMailboxContactListWorkerIntegrationTest.java
index d91ca40a085dabe83cd977f8c694c23c3941d6e7..414ea1052bee4d15d9180983de76b0090b90294c 100644
--- a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/OwnMailboxContactListWorkerIntegrationTest.java
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/OwnMailboxContactListWorkerIntegrationTest.java
@@ -6,14 +6,8 @@ import org.briarproject.bramble.api.crypto.SecretKey;
 import org.briarproject.bramble.api.db.DbException;
 import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorFactory;
-import org.briarproject.bramble.api.identity.Identity;
-import org.briarproject.bramble.api.identity.IdentityManager;
-import org.briarproject.bramble.api.lifecycle.LifecycleManager;
-import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
-import org.briarproject.bramble.api.mailbox.MailboxPairingState.Paired;
-import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
+import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.api.mailbox.MailboxProperties;
-import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.mailbox.lib.TestMailbox;
 import org.junit.After;
 import org.junit.Before;
@@ -21,23 +15,17 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.CountDownLatch;
 
-import static org.briarproject.bramble.api.mailbox.MailboxAuthToken.fromString;
 import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi;
-import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createTestComponent;
-import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.getQrCodePayload;
 import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.retryUntilSuccessOrTimeout;
 import static org.briarproject.bramble.test.TestUtils.getSecretKey;
-import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
 import static org.junit.Assert.assertEquals;
 
 public class OwnMailboxContactListWorkerIntegrationTest
-		extends BrambleTestCase {
+		extends AbstractMailboxIntegrationTest {
 
 	@Rule
 	public TemporaryFolder mailboxDataDirectory = new TemporaryFolder();
@@ -48,11 +36,7 @@ public class OwnMailboxContactListWorkerIntegrationTest
 
 	private MailboxProperties ownerProperties;
 
-	private final File testDir = getTestDirectory();
-	private final File aliceDir = new File(testDir, "alice");
-
-	private MailboxIntegrationTestComponent component;
-	private Identity identity;
+	private LocalAuthor localAuthor1;
 
 	private final SecretKey rootKey = getSecretKey();
 	private final long timestamp = System.currentTimeMillis();
@@ -62,27 +46,10 @@ public class OwnMailboxContactListWorkerIntegrationTest
 		mailbox = new TestMailbox(mailboxDataDirectory.getRoot());
 		mailbox.startLifecycle();
 
-		MailboxAuthToken setupToken = fromString(mailbox.getSetupToken());
-
-		component = createTestComponent(aliceDir);
-		identity = setUp(component, "Alice");
-
-		MailboxPairingTask pairingTask = component.getMailboxManager()
-				.startPairingTask(getQrCodePayload(setupToken));
-
-		CountDownLatch latch = new CountDownLatch(1);
-		pairingTask.addObserver((state) -> {
-			if (state instanceof Paired) {
-				latch.countDown();
-			}
-		});
-		latch.await();
+		c1 = startTestComponent(dir1, "Alice");
+		localAuthor1 = c1.getIdentityManager().getLocalAuthor();
 
-		ownerProperties = component.getDatabaseComponent()
-				.transactionWithNullableResult(false, txn ->
-						component.getMailboxSettingsManager()
-								.getOwnMailboxProperties(txn)
-				);
+		ownerProperties = pair(c1, mailbox);
 	}
 
 	@After
@@ -90,28 +57,15 @@ public class OwnMailboxContactListWorkerIntegrationTest
 		mailbox.stopLifecycle(true);
 	}
 
-	private Identity setUp(MailboxIntegrationTestComponent device, String name)
-			throws Exception {
-		// Add an identity for the user
-		IdentityManager identityManager = device.getIdentityManager();
-		Identity identity = identityManager.createIdentity(name);
-		identityManager.registerIdentity(identity);
-		// Start the lifecycle manager
-		LifecycleManager lifecycleManager = device.getLifecycleManager();
-		lifecycleManager.startServices(getSecretKey());
-		lifecycleManager.waitForStartup();
+	@Test
+	public void testUploadContacts() throws Exception {
 		// Check the initial conditions
-		ContactManager contactManager = device.getContactManager();
+		ContactManager contactManager = c1.getContactManager();
 		assertEquals(0, contactManager.getPendingContacts().size());
 		assertEquals(0, contactManager.getContacts().size());
-		return identity;
-	}
 
-	@Test
-	public void testUploadContacts() throws Exception {
 		int numContactsToAdd = 5;
-		List<ContactId> expectedContacts =
-				createContacts(component, identity, numContactsToAdd);
+		List<ContactId> expectedContacts = createContacts(c1, numContactsToAdd);
 
 		// Check for number of contacts on mailbox via API every 100ms
 		retryUntilSuccessOrTimeout(1000, 100, () -> {
@@ -125,15 +79,16 @@ public class OwnMailboxContactListWorkerIntegrationTest
 	}
 
 	private List<ContactId> createContacts(
-			MailboxIntegrationTestComponent component, Identity local,
-			int numContacts) throws DbException {
+			MailboxIntegrationTestComponent component, int numContacts)
+			throws DbException {
 		List<ContactId> contactIds = new ArrayList<>();
 		ContactManager contactManager = component.getContactManager();
 		AuthorFactory authorFactory = component.getAuthorFactory();
 		for (int i = 0; i < numContacts; i++) {
 			Author remote = authorFactory.createLocalAuthor("Bob " + i);
-			contactIds.add(contactManager.addContact(remote, local.getId(),
-					rootKey, timestamp, true, true, true));
+			ContactId c = contactManager.addContact(remote,
+					localAuthor1.getId(), rootKey, timestamp, true, true, true);
+			contactIds.add(c);
 		}
 		return contactIds;
 	}
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/TestUrlConverter.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/TestUrlConverter.java
deleted file mode 100644
index 5841e7cc97d9b26f0977a04b7fdd33ef700db4e2..0000000000000000000000000000000000000000
--- a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/TestUrlConverter.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.briarproject.bramble.mailbox;
-
-import org.briarproject.nullsafety.NotNullByDefault;
-
-import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.URL_BASE;
-
-@NotNullByDefault
-class TestUrlConverter implements UrlConverter {
-
-	@Override
-	public String convertOnionToBaseUrl(String onion) {
-		return URL_BASE;
-	}
-}
diff --git a/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/TestUrlConverterModule.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/TestUrlConverterModule.java
new file mode 100644
index 0000000000000000000000000000000000000000..a47ac069a2b53da5f7364f208cd860390e479b97
--- /dev/null
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/mailbox/TestUrlConverterModule.java
@@ -0,0 +1,20 @@
+package org.briarproject.bramble.mailbox;
+
+import org.briarproject.nullsafety.NotNullByDefault;
+
+import dagger.Module;
+import dagger.Provides;
+
+import static org.briarproject.bramble.mailbox.AbstractMailboxIntegrationTest.URL_BASE;
+
+@Module
+@NotNullByDefault
+class TestUrlConverterModule {
+
+	static UrlConverter urlConverter = onion -> URL_BASE;
+
+	@Provides
+	UrlConverter provideUrlConverter() {
+		return urlConverter;
+	}
+}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPlugin.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPlugin.java
similarity index 94%
rename from bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPlugin.java
rename to mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPlugin.java
index 8e68f4f35ad601dea92a0323105c052f0eeaf606..85111ea8b597bf793f1e27354a8afcb862ca8aa6 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPlugin.java
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPlugin.java
@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.Pair;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
 import org.briarproject.bramble.api.plugin.ConnectionHandler;
-import org.briarproject.bramble.api.plugin.PluginException;
 import org.briarproject.bramble.api.plugin.TorConstants;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
@@ -48,13 +47,13 @@ public class FakeTorPlugin implements DuplexPlugin {
 	}
 
 	@Override
-	public void start() throws PluginException {
+	public void start() {
 		LOG.info("Starting plugin");
 		state = ACTIVE;
 	}
 
 	@Override
-	public void stop() throws PluginException {
+	public void stop() {
 		LOG.info("Stopping plugin");
 		state = DISABLED;
 	}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPluginConfigModule.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPluginConfigModule.java
similarity index 60%
rename from bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPluginConfigModule.java
rename to mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPluginConfigModule.java
index 49b9048ad8827f4ff96deb9af431329379f8eeeb..de44712427ba5554ac09699d21916d7e28761a68 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPluginConfigModule.java
+++ b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPluginConfigModule.java
@@ -1,8 +1,10 @@
 package org.briarproject.bramble.test;
 
+import org.briarproject.bramble.api.plugin.PluginCallback;
 import org.briarproject.bramble.api.plugin.PluginConfig;
 import org.briarproject.bramble.api.plugin.TransportId;
 import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
+import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
 import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
 import org.briarproject.nullsafety.NotNullByDefault;
 
@@ -10,16 +12,41 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.Nullable;
+
 import dagger.Module;
 import dagger.Provides;
 
-import static java.util.Collections.emptyList;
 import static java.util.Collections.emptyMap;
 import static java.util.Collections.singletonList;
+import static org.briarproject.bramble.test.TestUtils.getTransportId;
 
 @Module
 public class FakeTorPluginConfigModule {
 
+	public static final TransportId SIMPLEX_TRANSPORT_ID = getTransportId();
+	private static final int MAX_LATENCY = 30_000; // 30 seconds
+
+	@NotNullByDefault
+	private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
+
+		@Override
+		public TransportId getId() {
+			return SIMPLEX_TRANSPORT_ID;
+		}
+
+		@Override
+		public long getMaxLatency() {
+			return MAX_LATENCY;
+		}
+
+		@Override
+		@Nullable
+		public SimplexPlugin createPlugin(PluginCallback callback) {
+			return null;
+		}
+	};
+
 	@Provides
 	PluginConfig providePluginConfig(FakeTorPluginFactory tor) {
 		@NotNullByDefault
@@ -32,7 +59,7 @@ public class FakeTorPluginConfigModule {
 
 			@Override
 			public Collection<SimplexPluginFactory> getSimplexFactories() {
-				return emptyList();
+				return singletonList(simplex);
 			}
 
 			@Override
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPluginFactory.java b/mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPluginFactory.java
similarity index 100%
rename from bramble-core/src/test/java/org/briarproject/bramble/test/FakeTorPluginFactory.java
rename to mailbox-integration-tests/src/test/java/org/briarproject/bramble/test/FakeTorPluginFactory.java