diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java
index a84870f89d..efb30757b7 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java
@@ -1,4 +1,3 @@
-
 package org.mage.test.cards.single;
 
 import mage.constants.PhaseStep;
@@ -7,8 +6,7 @@ import org.junit.Test;
 import org.mage.test.serverside.base.CardTestPlayerBase;
 
 /**
- *
- * @author LevelX2
+ * @author LevelX2, JayDi85
  */
 
 public class MisdirectionTest extends CardTestPlayerBase {
@@ -17,10 +15,58 @@ public class MisdirectionTest extends CardTestPlayerBase {
      * Tests if Misdirection for target opponent works correctly
      * https://github.com/magefree/mage/issues/574
      */
+
     @Test
-    public void testChangeTargetOpponent() {
+    public void test_RakshaDiscardWorks() {
         // Target opponent discards two cards. Put the top two cards of your library into your graveyard.
-        addCard(Zone.HAND, playerA, "Rakshasa's Secret");
+        addCard(Zone.HAND, playerA, "Rakshasa's Secret"); // {2}{B}
+        addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
+        addCard(Zone.HAND, playerB, "Silvercoat Lion", 2);
+        addCard(Zone.HAND, playerB, "Ashcoat Bear", 5);
+
+        // A cast discard
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakshasa's Secret", playerB);
+        setChoice(playerB, "Silvercoat Lion"); // select target 1
+        setChoice(playerB, "Silvercoat Lion"); // select target 2
+        checkHandCardCount("B haven't lions", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
+        checkHandCardCount("B have 5 bears", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Ashcoat Bear", 5);
+
+        setStopAt(1, PhaseStep.END_TURN);
+        execute();
+        assertAllCommandsUsed();
+    }
+
+    @Test
+    public void test_MisdirectionRetargetWorks() {
+        // Return target permanent to its owner’s hand.
+        addCard(Zone.HAND, playerA, "Boomerang", 1); // {U}{U}
+        addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
+        addCard(Zone.BATTLEFIELD, playerA, "Ashcoat Bear", 1);
+        // Change the target of target spell with a single target.
+        addCard(Zone.HAND, playerB, "Misdirection"); // {3}{U}{U}
+        addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
+        addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
+
+        // A cast Boomerang to remove lion
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Silvercoat Lion");
+        // B counter it by Misdirection and remove bear
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Boomerang", "Boomerang");
+        addTarget(playerB, "Ashcoat Bear");
+
+        setStopAt(1, PhaseStep.END_TURN);
+        execute();
+        assertAllCommandsUsed();
+
+        assertGraveyardCount(playerA, "Boomerang", 1);
+        assertPermanentCount(playerA, "Ashcoat Bear", 0);
+        assertGraveyardCount(playerB, "Misdirection", 1);
+        assertPermanentCount(playerB, "Silvercoat Lion", 1);
+    }
+
+    @Test
+    public void test_MisdirectionCantTargetToIllegal() {
+        // Target opponent discards two cards. Put the top two cards of your library into your graveyard.
+        addCard(Zone.HAND, playerA, "Rakshasa's Secret"); // {2}{B}
         addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
         /*    
         Misdirection {3}{U}{U}
@@ -30,23 +76,31 @@ public class MisdirectionTest extends CardTestPlayerBase {
         */
         addCard(Zone.HAND, playerB, "Misdirection");
         addCard(Zone.HAND, playerB, "Silvercoat Lion", 2);
+        addCard(Zone.HAND, playerB, "Ashcoat Bear", 5);
         addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
-        
+
+        // cast Raksha and select B
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakshasa's Secret", playerB);
+        // cast misdir, but it's not apply and taget will be same
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Rakshasa's Secret", "Rakshasa's Secret");
-        addTarget(playerB, playerA); // only legal target is player B as opponent - so player A should not be allowed
-        
-        setStopAt(1, PhaseStep.BEGIN_COMBAT);
+        // B must select cards to discard (2 lions, not bears)
+        setChoice(playerB, "Silvercoat Lion"); // select target 1
+        setChoice(playerB, "Silvercoat Lion"); // select target 2
+        checkHandCardCount("B haven't lions", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
+        checkHandCardCount("B have 5 bears", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Ashcoat Bear", 5);
+
+        setStopAt(1, PhaseStep.END_TURN);
         execute();
+        assertAllCommandsUsed();
 
         assertGraveyardCount(playerA, "Rakshasa's Secret", 1);
         assertGraveyardCount(playerB, "Misdirection", 1);
         assertHandCount(playerB, "Silvercoat Lion", 0);
     }
-    
+
     // check to change target permanent creature legal to to a creature the opponent of the spell controller controls
     @Test
-    public void testChangePublicExecution() {
+    public void test_ChangePublicExecution() {
         // Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn.
         addCard(Zone.HAND, playerA, "Public Execution");
         addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
@@ -60,26 +114,27 @@ public class MisdirectionTest extends CardTestPlayerBase {
         addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
         addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3
         addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
-        
+
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Pillarfield Ox");
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution");
-        addTarget(playerB, "Custodian of the Trove"); 
-        
+        addTarget(playerB, "Custodian of the Trove");
+
         setStopAt(1, PhaseStep.BEGIN_COMBAT);
         execute();
+        assertAllCommandsUsed();
 
         assertGraveyardCount(playerA, "Public Execution", 1);
         assertGraveyardCount(playerB, "Misdirection", 1);
-        
-        assertGraveyardCount(playerB, "Custodian of the Trove",1);
+
+        assertGraveyardCount(playerB, "Custodian of the Trove", 1);
         assertPermanentCount(playerB, "Pillarfield Ox", 1);
         assertPowerToughness(playerB, "Pillarfield Ox", 0, 4);
 
-    } 
-    
+    }
+
     // check to change target permanent creature not legal to to a creature the your opponent controls
     @Test
-    public void testChangePublicExecution2() {
+    public void test_ChangePublicExecution2() {
         // Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn.
         addCard(Zone.HAND, playerA, "Public Execution");
         addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
@@ -94,13 +149,13 @@ public class MisdirectionTest extends CardTestPlayerBase {
         addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
         addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3
         addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
-        
+
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Custodian of the Trove");
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution");
-        addTarget(playerB, "Keeper of the Lens"); 
-        
+
         setStopAt(1, PhaseStep.BEGIN_COMBAT);
         execute();
+        assertAllCommandsUsed();
 
         assertGraveyardCount(playerA, "Public Execution", 1);
         assertGraveyardCount(playerB, "Misdirection", 1);
@@ -108,8 +163,7 @@ public class MisdirectionTest extends CardTestPlayerBase {
 
         assertPermanentCount(playerB, "Pillarfield Ox", 1);
         assertPowerToughness(playerB, "Pillarfield Ox", 0, 4);
-        
-        assertGraveyardCount(playerB, "Custodian of the Trove",1);
 
-    }        
+        assertGraveyardCount(playerB, "Custodian of the Trove", 1);
+    }
 }
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java
index cb9a905962..7e9d8b2cf1 100644
--- a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java
@@ -3,9 +3,11 @@ package org.mage.test.player;
 import mage.MageObject;
 import mage.abilities.ActivatedAbility;
 import mage.abilities.SpellAbility;
+import mage.constants.Outcome;
 import mage.constants.RangeOfInfluence;
 import mage.game.Game;
 import mage.player.ai.ComputerPlayer;
+import mage.target.Target;
 
 import java.util.LinkedHashMap;
 import java.util.UUID;
@@ -59,4 +61,13 @@ public class TestComputerPlayer extends ComputerPlayer {
         // default implementation by AI
         return super.chooseSpellAbilityForCast(ability, game, noMana);
     }
+
+    @Override
+    public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
+        // copy-paste for TestComputerXXX
+
+        // workaround for discard spells
+        // reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
+        return testPlayerLink.choose(outcome, target, sourceId, game);
+    }
 }
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java
index 3bff415070..e647128bb6 100644
--- a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java
@@ -3,9 +3,11 @@ package org.mage.test.player;
 import mage.MageObject;
 import mage.abilities.ActivatedAbility;
 import mage.abilities.SpellAbility;
+import mage.constants.Outcome;
 import mage.constants.RangeOfInfluence;
 import mage.game.Game;
 import mage.player.ai.ComputerPlayer7;
+import mage.target.Target;
 
 import java.util.LinkedHashMap;
 import java.util.UUID;
@@ -59,4 +61,13 @@ public class TestComputerPlayer7 extends ComputerPlayer7 {
         // default implementation by AI
         return super.chooseSpellAbilityForCast(ability, game, noMana);
     }
+
+    @Override
+    public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
+        // copy-paste for TestComputerXXX
+
+        // workaround for discard spells
+        // reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
+        return testPlayerLink.choose(outcome, target, sourceId, game);
+    }
 }
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
index 7d70c34d4a..c1aff1cb7f 100644
--- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
@@ -1160,11 +1160,16 @@ public class TestPlayer implements Player {
     @Override
     public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map<String, Serializable> options) {
         if (!choices.isEmpty()) {
+
+            List<String> usedChoices = new ArrayList<>();
+            List<UUID> usedTargets = new ArrayList<>();
+
             Ability source = null;
             StackObject stackObject = game.getStack().getStackObject(sourceId);
             if (stackObject != null) {
                 source = stackObject.getStackAbility();
             }
+
             if ((target instanceof TargetPermanent) || (target instanceof TargetPermanentOrPlayer)) { // player target not implemted yet
                 FilterPermanent filterPermanent;
                 if (target instanceof TargetPermanentOrPlayer) {
@@ -1218,6 +1223,7 @@ public class TestPlayer implements Player {
                     }
                 }
             }
+
             if (target instanceof TargetPlayer) {
                 for (Player player : game.getPlayers().values()) {
                     for (String choose2 : choices) {
@@ -1231,42 +1237,74 @@ public class TestPlayer implements Player {
                     }
                 }
             }
+
+            // TODO: add same choices fixes for other target types (one choice must uses only one time for one target)
             if (target instanceof TargetCard) {
-                TargetCard targetCard = ((TargetCard) target);
-                Set<UUID> possibleTargets = targetCard.possibleTargets(sourceId, target.getTargetController() == null ? getId() : target.getTargetController(), game);
-                for (String choose2 : choices) {
-                    String[] targetList = choose2.split("\\^");
+                // one choice per target
+                // only unique targets
+                //TargetCard targetFull = ((TargetCard) target);
+
+                usedChoices.clear();
+                usedTargets.clear();
+                boolean targetCompleted = false;
+
+                CheckAllChoices:
+                for (String choiceRecord : choices) {
+                    if (targetCompleted) {
+                        break CheckAllChoices;
+                    }
+
                     boolean targetFound = false;
-                    Choice:
-                    for (String targetName : targetList) {
-                        for (UUID targetId : possibleTargets) {
+                    String[] possibleChoices = choiceRecord.split("\\^");
+
+                    CheckOneChoice:
+                    for (String possibleChoice : possibleChoices) {
+                        Set<UUID> possibleCards = target.possibleTargets(sourceId, target.getTargetController() == null ? getId() : target.getTargetController(), game);
+                        CheckTargetsList:
+                        for (UUID targetId : possibleCards) {
                             MageObject targetObject = game.getObject(targetId);
-                            if (targetObject != null) {
-                                if (targetObject.getName().equals(targetName)) {
-                                    if (targetCard.canTarget(targetObject.getId(), game)) {
-                                        if (targetCard.getTargets() != null && !targetCard.getTargets().contains(targetObject.getId())) {
-                                            targetCard.add(targetObject.getId(), game);
-                                            targetFound = true;
-                                            if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
-                                                break Choice;
-                                            }
-                                        }
+                            if (targetObject != null && targetObject.getName().equals(possibleChoice)) {
+                                if (target.canTarget(targetObject.getId(), game)) {
+                                    // only unique targets
+                                    if (usedTargets.contains(targetObject.getId())) {
+                                        continue;
                                     }
+
+                                    // OK, can use it
+                                    target.add(targetObject.getId(), game);
+                                    targetFound = true;
+                                    usedTargets.add(targetObject.getId());
+
+                                    // break on full targets list
+                                    if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
+                                        targetCompleted = true;
+                                        break CheckOneChoice;
+                                    }
+
+                                    // restart search
+                                    break CheckTargetsList;
                                 }
                             }
-
                         }
                     }
+
                     if (targetFound) {
-                        if (targetCard.isChosen()) {
-                            choices.remove(choose2);
-                            return true;
-                        } else {
-                            target.clearChosen();
-                        }
+                        usedChoices.add(choiceRecord);
+                    }
+                }
+
+                // apply only on ALL targets or revert
+                if (usedChoices.size() > 0) {
+                    if (target.isChosen()) {
+                        choices.removeAll(usedChoices);
+                        return true;
+                    } else {
+                        Assert.fail("Not full targets list.");
+                        target.clearChosen();
                     }
                 }
             }
+
             if (target instanceof TargetSource) {
                 Set<UUID> possibleTargets;
                 TargetSource t = ((TargetSource) target);
@@ -2774,7 +2812,7 @@ public class TestPlayer implements Player {
 
     @Override
     public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
-        Assert.fail("That's method calls only from computerPlayer->cast(), see TestComputerPlayerXXX");
+        Assert.fail("That's method must calls only from computerPlayer->cast(), see TestComputerPlayerXXX");
         return computerPlayer.chooseSpellAbilityForCast(ability, game, noMana);
     }
 
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
index 5a93697bd3..9daed70295 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
@@ -1132,17 +1132,17 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
     }
 
     public void assertActionsCount(TestPlayer player, int count) throws AssertionError {
-        Assert.assertEquals("(Actions " + player.getName() + ") Count are not equel (founded ["
+        Assert.assertEquals("(Actions of " + player.getName() + ") Count are not equel (founded ["
                 + player.getActions().stream().map(PlayerAction::getAction).collect(Collectors.joining(", "))
                 + "])", count, player.getActions().size());
     }
 
     public void assertChoicesCount(TestPlayer player, int count) throws AssertionError {
-        Assert.assertEquals("(Choices " + player.getName() + ") Count are not equel (founded " + player.getChoices() + ")", count, player.getChoices().size());
+        Assert.assertEquals("(Choices of " + player.getName() + ") Count are not equel (founded " + player.getChoices() + ")", count, player.getChoices().size());
     }
 
     public void assertTargetsCount(TestPlayer player, int count) throws AssertionError {
-        Assert.assertEquals("(Targets " + player.getName() + ") Count are not equel (founded " + player.getTargets() + ")", count, player.getTargets().size());
+        Assert.assertEquals("(Targets of " + player.getName() + ") Count are not equel (founded " + player.getTargets() + ")", count, player.getTargets().size());
     }
 
     public void assertAllCommandsUsed() throws AssertionError {