Index: trunk/test/unit/org/openstreetmap/josm/actions/CopyActionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/CopyActionTest.java	(revision 10599)
+++ trunk/test/unit/org/openstreetmap/josm/actions/CopyActionTest.java	(revision 10604)
@@ -3,13 +3,29 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
 import java.util.Arrays;
-import java.util.Collections;
 
-import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
-import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
+import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
@@ -17,31 +33,88 @@
  */
 public class CopyActionTest {
+    private static final class CapturingCopyAction extends CopyAction {
+        private boolean warningShown;
 
-    /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init();
+        @Override
+        protected void showEmptySelectionWarning() {
+            warningShown = true;
+        }
     }
 
     /**
-     * Test of {@link CopyAction#getCopyString} method for a single way.
+     * We need prefs for this.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().platform().fakeAPI();
+
+    /**
+     * Test that copy action copies the selected primitive
+     * @throws IOException if an I/O error occurs
+     * @throws UnsupportedFlavorException if the requested data flavor is not supported
      */
     @Test
-    public void testCopyStringWay() {
-        final Way way = new Way(123L);
-        assertEquals("way 123", CopyAction.getCopyString(Collections.singleton(way)));
+    public void testWarnOnEmpty() throws UnsupportedFlavorException, IOException {
+        Clipboard clipboard = ClipboardUtils.getClipboard();
+        clipboard.setContents(new StringSelection("test"), null);
+
+        CapturingCopyAction action = new CapturingCopyAction();
+
+        action.updateEnabledState();
+        assertFalse(action.isEnabled());
+        action.actionPerformed(null);
+        assertTrue(action.warningShown);
+
+        Main.getLayerManager().addLayer(new OsmDataLayer(new DataSet(), "test", null));
+        action.warningShown = false;
+
+        action.updateEnabledState();
+        assertFalse(action.isEnabled());
+        action.actionPerformed(null);
+        assertTrue(action.warningShown);
+
+        assertEquals("test", clipboard.getContents(null).getTransferData(DataFlavor.stringFlavor));
     }
 
     /**
-     * Test of {@link CopyAction#getCopyString} method for a way and a relation.
+     * Test that copy action copies the selected primitive
+     * @throws Exception if an error occurs
      */
     @Test
-    public void testCopyStringWayRelation() {
-        final Way way = new Way(123L);
-        final Relation relation = new Relation(456);
-        assertEquals("way 123,relation 456", CopyAction.getCopyString(Arrays.asList(way, relation)));
-        assertEquals("relation 456,way 123", CopyAction.getCopyString(Arrays.asList(relation, way)));
+    public void testCopySinglePrimitive() throws Exception {
+        DataSet data = new DataSet();
+
+        Node node1 = new Node();
+        node1.setCoor(LatLon.ZERO);
+        data.addPrimitive(node1);
+
+        Node node2 = new Node();
+        node2.setCoor(LatLon.ZERO);
+        data.addPrimitive(node2);
+        Way way = new Way();
+        way.setNodes(Arrays.asList(node1, node2));
+        data.addPrimitive(way);
+        data.setSelected(way);
+
+        Main.getLayerManager().addLayer(new OsmDataLayer(data, "test", null));
+
+        CopyAction action = new CopyAction() {
+            @Override
+            protected void showEmptySelectionWarning() {
+                fail("Selection is not empty.");
+            }
+        };
+        action.updateEnabledState();
+        assertTrue(action.isEnabled());
+        action.actionPerformed(null);
+
+        Object copied = ClipboardUtils.getClipboard().getContents(null).getTransferData(PrimitiveTransferData.DATA_FLAVOR);
+        assertNotNull(copied);
+        assertTrue(copied instanceof PrimitiveTransferData);
+        PrimitiveTransferData ptd = (PrimitiveTransferData) copied;
+        Object[] direct = ptd.getDirectlyAdded().toArray();
+        assertEquals(1, direct.length);
+        Object[] referenced = ptd.getReferenced().toArray();
+        assertEquals(2, referenced.length);
     }
 }
Index: trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/ClipboardUtilsTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/ClipboardUtilsTest.java	(revision 10604)
+++ trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/ClipboardUtilsTest.java	(revision 10604)
@@ -0,0 +1,122 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.datatransfer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Basic tests for the clipboard utils class.
+ * @author Michael Zangl
+ */
+public class ClipboardUtilsTest {
+    private static final class ThrowIllegalStateClipboard extends Clipboard {
+        private int failingAccesses = 3;
+
+        private ThrowIllegalStateClipboard(String name) {
+            super(name);
+        }
+
+        @Override
+        public synchronized Transferable getContents(Object requestor) {
+            if (failingAccesses >= 0) {
+                failingAccesses--;
+                throw new IllegalStateException();
+            }
+            return super.getContents(requestor);
+        }
+
+        protected synchronized void setFailingAccesses(int failingAccesses) {
+            this.failingAccesses = failingAccesses;
+        }
+    }
+
+    private static final class SupportNothingTransferable implements Transferable {
+        @Override
+        public boolean isDataFlavorSupported(DataFlavor flavor) {
+            return false;
+        }
+
+        @Override
+        public DataFlavor[] getTransferDataFlavors() {
+            return new DataFlavor[0];
+        }
+
+        @Override
+        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+            throw new UnsupportedFlavorException(flavor);
+        }
+    }
+
+    /**
+     * No dependencies
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules();
+
+    /**
+     * Test {@link ClipboardUtils#getClipboard()}
+     */
+    @Test
+    public void testGetClipboard() {
+        Clipboard c = ClipboardUtils.getClipboard();
+        assertNotNull(c);
+        assertSame(c, ClipboardUtils.getClipboard());
+    }
+
+    /**
+     * Test {@link ClipboardUtils#copyString(String)} and {@link ClipboardUtils#getClipboardStringContent()}
+     */
+    @Test
+    public void testCopyPasteString() {
+        ClipboardUtils.copyString("");
+        assertEquals("", ClipboardUtils.getClipboardStringContent());
+        ClipboardUtils.copyString("xxx\nx");
+        assertEquals("xxx\nx", ClipboardUtils.getClipboardStringContent());
+
+        ClipboardUtils.copy(new SupportNothingTransferable());
+        assertEquals(null, ClipboardUtils.getClipboardStringContent());
+    }
+
+    /**
+     * Test that {@link ClipboardUtils#getClipboardContent(Clipboard)} handles illegal state exceptions
+     */
+    @Test
+    public void testGetContentIllegalState() {
+        ThrowIllegalStateClipboard throwingClipboard = new ThrowIllegalStateClipboard("test");
+
+        throwingClipboard.setContents(new StringSelection(""), null);
+        Transferable content = ClipboardUtils.getClipboardContent(throwingClipboard);
+        assertTrue(content.isDataFlavorSupported(DataFlavor.stringFlavor));
+
+        throwingClipboard.setFailingAccesses(50);
+        content = ClipboardUtils.getClipboardContent(new ThrowIllegalStateClipboard("test"));
+        assertNull(content);
+    }
+
+    /**
+     * Test that {@link ClipboardUtils#getSystemSelection()} works in headless mode.
+     */
+    @Test
+    public void testSystemSelectionDoesNotFail() {
+        assertTrue(GraphicsEnvironment.isHeadless());
+        assertNull(ClipboardUtils.getSystemSelection());
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferableTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferableTest.java	(revision 10599)
+++ trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/PrimitiveTransferableTest.java	(revision 10604)
@@ -5,16 +5,22 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable.PRIMITIVE_DATA;
 
 import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.UnsupportedFlavorException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 
-import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.NodeData;
 import org.openstreetmap.josm.data.osm.PrimitiveData;
+import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
+import org.openstreetmap.josm.gui.datatransfer.data.TagTransferData;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
@@ -22,22 +28,27 @@
  */
 public class PrimitiveTransferableTest {
+    /**
+     * Prefs to use OSM primitives
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences();
 
     /**
-     * Setup tests
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init();
-    }
-
-    /**
-     * Test of {@link PrimitiveTransferable#getTransferDataFlavors()} method.
+     * Test of {@link PrimitiveTransferable#getTransferDataFlavors()} method response order
      */
     @Test
     public void testGetTransferDataFlavors() {
-        DataFlavor[] flavors = new PrimitiveTransferable(null).getTransferDataFlavors();
-        assertEquals(2, flavors.length);
-        assertEquals(PRIMITIVE_DATA, flavors[0]);
-        assertEquals(DataFlavor.stringFlavor, flavors[1]);
+        List<DataFlavor> flavors = Arrays.asList(new PrimitiveTransferable(null).getTransferDataFlavors());
+        int ptd = flavors.indexOf(PrimitiveTransferData.DATA_FLAVOR);
+        int tags = flavors.indexOf(TagTransferData.FLAVOR);
+        int string = flavors.indexOf(DataFlavor.stringFlavor);
+
+        assertTrue(ptd >= 0);
+        assertTrue(tags >= 0);
+        assertTrue(string >= 0);
+
+        assertTrue(ptd < tags);
+        assertTrue(tags < string);
     }
 
@@ -47,6 +58,6 @@
     @Test
     public void testIsDataFlavorSupported() {
-        assertTrue(new PrimitiveTransferable(null).isDataFlavorSupported(PRIMITIVE_DATA));
-        assertFalse(new PrimitiveTransferable(null).isDataFlavorSupported(null));
+        assertTrue(new PrimitiveTransferable(null).isDataFlavorSupported(PrimitiveTransferData.DATA_FLAVOR));
+        assertFalse(new PrimitiveTransferable(null).isDataFlavorSupported(DataFlavor.imageFlavor));
     }
 
@@ -57,9 +68,15 @@
     @Test
     public void testGetTransferDataNominal() throws UnsupportedFlavorException {
-        PrimitiveTransferable pt = new PrimitiveTransferable(Collections.singleton(new Node(1)));
-        assertEquals("node 1 # incomplete\n", pt.getTransferData(DataFlavor.stringFlavor));
-        Collection<PrimitiveData> td = ((PrimitiveTransferable.Data) pt.getTransferData(PRIMITIVE_DATA)).getPrimitiveData();
+        PrimitiveTransferData data = PrimitiveTransferData.getData(Collections.singleton(new Node(1)));
+        PrimitiveTransferable pt = new PrimitiveTransferable(data);
+        assertEquals("node 1", pt.getTransferData(DataFlavor.stringFlavor));
+        Collection<PrimitiveData> td = ((PrimitiveTransferData) pt.getTransferData(PrimitiveTransferData.DATA_FLAVOR)).getAll();
         assertEquals(1, td.size());
-        assertTrue(td.iterator().next() instanceof PrimitiveData);
+        assertTrue(td.iterator().next() instanceof NodeData);
+
+
+        data = PrimitiveTransferData.getData(Arrays.asList(new Node(1), new Node(2)));
+        pt = new PrimitiveTransferable(data);
+        assertEquals("node 1\nnode 2", pt.getTransferData(DataFlavor.stringFlavor));
     }
 
@@ -70,5 +87,6 @@
     @Test(expected = UnsupportedFlavorException.class)
     public void testGetTransferDataError() throws UnsupportedFlavorException {
-        new PrimitiveTransferable(Collections.singleton(new Node(1))).getTransferData(null);
+        PrimitiveTransferData data = PrimitiveTransferData.getData(Collections.singleton(new Node(1)));
+        new PrimitiveTransferable(data).getTransferData(DataFlavor.imageFlavor);
     }
 }
Index: trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/RelationMemberTransferableTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/RelationMemberTransferableTest.java	(revision 10599)
+++ trunk/test/unit/org/openstreetmap/josm/gui/datatransfer/RelationMemberTransferableTest.java	(revision 10604)
@@ -38,5 +38,5 @@
     @Test
     public void testGetTransferDataFlavors() {
-        DataFlavor[] flavors = new RelationMemberTransferable(null).getTransferDataFlavors();
+        DataFlavor[] flavors = new RelationMemberTransferable(Collections.<RelationMember>emptyList()).getTransferDataFlavors();
         assertEquals(2, flavors.length);
         assertEquals(RELATION_MEMBER_DATA, flavors[0]);
@@ -49,6 +49,7 @@
     @Test
     public void testIsDataFlavorSupported() {
-        assertTrue(new RelationMemberTransferable(null).isDataFlavorSupported(RELATION_MEMBER_DATA));
-        assertFalse(new RelationMemberTransferable(null).isDataFlavorSupported(null));
+        RelationMemberTransferable transferable = new RelationMemberTransferable(Collections.<RelationMember>emptyList());
+        assertTrue(transferable.isDataFlavorSupported(RELATION_MEMBER_DATA));
+        assertFalse(transferable.isDataFlavorSupported(null));
     }
 
Index: trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorActionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorActionTest.java	(revision 10604)
+++ trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorActionTest.java	(revision 10604)
@@ -0,0 +1,72 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditorTest;
+import org.openstreetmap.josm.gui.dialogs.relation.IRelationEditor;
+import org.openstreetmap.josm.gui.dialogs.relation.MemberTable;
+import org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel;
+import org.openstreetmap.josm.gui.dialogs.relation.SelectionTableModel;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetHandler;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * This class provides the basic test environment for relation editor actions.
+ * @author Michael Zangl
+ */
+public abstract class AbstractRelationEditorActionTest {
+    /**
+     * Platform for tooltips.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().platform();
+
+    protected SelectionTableModel selectionTableModel;
+
+    protected IRelationEditor editor;
+
+    protected MemberTable memberTable;
+
+    protected OsmDataLayer layer;
+
+    protected MemberTableModel memberTableModel;
+
+    /**
+     * Set up the test data required for common tests using one relation.
+     */
+    @Before
+    public void setupTestData() {
+        DataSet ds = new DataSet();
+        final Relation orig = new Relation(1);
+        ds.addPrimitive(orig);
+        layer = new OsmDataLayer(ds, "test", null);
+        memberTableModel = new MemberTableModel(orig, layer, new TaggingPresetHandler() {
+            @Override
+            public void updateTags(List<Tag> tags) {
+            }
+
+            @Override
+            public Collection<OsmPrimitive> getSelection() {
+                return Collections.<OsmPrimitive>singleton(orig);
+            }
+        });
+        selectionTableModel = new SelectionTableModel(layer);
+
+        editor = GenericRelationEditorTest.newRelationEditor(orig, layer);
+
+        memberTable = new MemberTable(layer, editor.getRelation(), memberTableModel);
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersActionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersActionTest.java	(revision 10604)
+++ trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/PasteMembersActionTest.java	(revision 10604)
@@ -0,0 +1,126 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.relation.actions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.junit.Test;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.gui.datatransfer.ClipboardUtils;
+import org.openstreetmap.josm.gui.datatransfer.PrimitiveTransferable;
+import org.openstreetmap.josm.gui.datatransfer.RelationMemberTransferable;
+import org.openstreetmap.josm.gui.datatransfer.data.PrimitiveTransferData;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+
+/**
+ * Test for {@link PasteMembersAction}
+ * @author Michael Zangl
+ */
+public class PasteMembersActionTest extends AbstractRelationEditorActionTest {
+    /**
+     * Test {@link PasteMembersAction#isEnabled()}
+     */
+    @Test
+    public void testEnabledState() {
+        copyString();
+
+        PasteMembersAction action = new PasteMembersAction(memberTable, layer, editor);
+        ClipboardUtils.getClipboard().addFlavorListener(action);
+
+        try {
+            assertFalse(action.isEnabled());
+
+            Node node = new Node();
+            copyNode(node);
+            syncListener();
+            assertTrue(action.isEnabled());
+
+            copyMember(node);
+            syncListener();
+            assertTrue(action.isEnabled());
+
+            copyString();
+            syncListener();
+            assertFalse(action.isEnabled());
+        } finally {
+            ClipboardUtils.getClipboard().removeFlavorListener(action);
+        }
+    }
+
+    private void syncListener() {
+        GuiHelper.runInEDTAndWait(() -> {
+            // nop
+        });
+    }
+
+    /**
+     * Test that pasting produces the result required
+     */
+    @Test
+    public void testActionWrongClipboard() {
+        copyString();
+        PasteMembersAction action = new PasteMembersAction(memberTable, layer, editor);
+        action.actionPerformed(null);
+
+        Relation relation = new Relation(1);
+        memberTableModel.applyToRelation(relation);
+        assertEquals(0, relation.getMembersCount());
+    }
+
+    /**
+     * Test that pasting produces the result required
+     */
+    @Test
+    public void testActionForMembers() {
+        Node testNode = new Node(10);
+        layer.data.addPrimitive(testNode);
+        copyMember(testNode);
+        PasteMembersAction action = new PasteMembersAction(memberTable, layer, editor);
+        action.actionPerformed(null);
+
+        Relation relation = new Relation(1);
+        memberTableModel.applyToRelation(relation);
+        assertEquals(1, relation.getMembersCount());
+        assertEquals("test", relation.getMember(0).getRole());
+        assertSame(testNode, relation.getMember(0).getMember());
+    }
+
+    /**
+     * Test that pasting primitvies produces the result required
+     */
+    @Test
+    public void testActionForPrimitives() {
+        Node testNode = new Node(10);
+        layer.data.addPrimitive(testNode);
+        copyNode(testNode);
+        PasteMembersAction action = new PasteMembersAction(memberTable, layer, editor);
+        action.actionPerformed(null);
+
+        Relation relation = new Relation(1);
+        memberTableModel.applyToRelation(relation);
+        assertEquals(1, relation.getMembersCount());
+        assertEquals("", relation.getMember(0).getRole());
+        assertSame(testNode, relation.getMember(0).getMember());
+    }
+
+    private void copyNode(Node node) {
+        PrimitiveTransferData data = PrimitiveTransferData.getData(Collections.singleton(node));
+        ClipboardUtils.copy(new PrimitiveTransferable(data));
+    }
+
+    private void copyMember(Node node) {
+        Set<RelationMember> members = Collections.singleton(new RelationMember("test", node));
+        ClipboardUtils.copy(new RelationMemberTransferable(members));
+    }
+
+    private void copyString() {
+        ClipboardUtils.copyString("");
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/RelationEditorActionsTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/RelationEditorActionsTest.java	(revision 10599)
+++ trunk/test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/RelationEditorActionsTest.java	(revision 10604)
@@ -2,7 +2,6 @@
 package org.openstreetmap.josm.gui.dialogs.relation.actions;
 
-import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
-import org.openstreetmap.josm.JOSMFixture;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -15,4 +14,7 @@
 import org.openstreetmap.josm.gui.tagging.TagEditorModel;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
@@ -20,15 +22,13 @@
  */
 public class RelationEditorActionsTest {
+    /**
+     * Plattform for tooltips.
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences().platform().commands();
 
     /**
-     * Setup test.
-     */
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        JOSMFixture.createUnitTestFixture().init(true);
-    }
-
-    /**
-     * Test all actions with minimal data.
+     * Check that all actions do not crash.
      */
     @Test
@@ -58,5 +58,5 @@
 
         new CopyMembersAction(memberTableModel, layer, editor).actionPerformed(null);
-        new PasteMembersAction(memberTableModel, layer, editor).actionPerformed(null);
+        new PasteMembersAction(memberTable, layer, editor).actionPerformed(null);
 
         new DeleteCurrentRelationAction(layer, editor).actionPerformed(null);
Index: trunk/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java	(revision 10599)
+++ trunk/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java	(revision 10604)
@@ -12,4 +12,5 @@
 import org.junit.runners.model.InitializationError;
 import org.junit.runners.model.Statement;
+import org.openstreetmap.josm.JOSMFixture;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.projection.Projections;
@@ -40,4 +41,5 @@
     private boolean platform;
     private boolean useProjection;
+    private boolean commands;
     private boolean allowMemoryManagerLeaks;
 
@@ -132,4 +134,13 @@
     public JOSMTestRules projection() {
         useProjection = true;
+        return this;
+    }
+
+    /**
+      * Allow the execution of commands using {@link Main#undoRedo}
+      * @return this instance, for easy chaining
+      */
+    public JOSMTestRules commands() {
+        commands = true;
         return this;
     }
@@ -221,4 +232,9 @@
         if (platform) {
             Main.determinePlatformHook();
+        }
+
+        if (commands) {
+            // TODO: Implement a more selective version of this once Main is restructured.
+            JOSMFixture.createUnitTestFixture().init(true);
         }
     }
