using FakeItEasy; using MiniJeuxFinal.Games; using MiniJeuxFinal.Games.PierrePapierCiseaux; using MiniJeuxFinal.Games.PierrePapierCiseaux.Actions; using NFluent; using System.Reflection; namespace MiniJeuxFinal.Test.Games.PierrePapierCiseaux { public class PierrePapierCiseauxGameTests { private readonly IPlayer _fakePlayer; private readonly IPlayer _fakeComputer; private readonly PierrePapierCiseauxGame _target; public PierrePapierCiseauxGameTests() { _fakePlayer = A.Fake(); _fakeComputer = A.Fake(); _target = new PierrePapierCiseauxGame(totalRound: 3, _fakePlayer, _fakeComputer); } [Fact] public void Name_Should_Return_Correct_Game_Name() { Check.That(_target.Name).IsEqualTo("Jeu du Pierre, Papier, Ciseaux 🧱 📄 ✂️"); } [Fact] public void Constructor_Should_Set_Properties_Correctly() { const int totalRounds = 5; var player = A.Fake(); var computer = A.Fake(); var game = new PierrePapierCiseauxGame(totalRounds, player, computer); Check.That(game).IsNotNull(); } [Fact] public void Start_Should_End_Game_When_Computer_Reaches_TotalRounds() { A.CallTo(() => _fakePlayer.Score).Returns(0); A.CallTo(() => _fakeComputer.Score).ReturnsNextFromSequence(0, 1, 2, 3); // Atteint 3 var fakePlayerAction = A.Fake(); var fakeComputerAction = A.Fake(); A.CallTo(() => fakePlayerAction.ToWin(fakeComputerAction)).Returns(false); A.CallTo(() => fakeComputerAction.ToWin(fakePlayerAction)).Returns(true); A.CallTo(() => _fakePlayer.Play()).Returns(fakePlayerAction); A.CallTo(() => _fakeComputer.Play()).Returns(fakeComputerAction); IPlayer? capturedWinner = null; _target.GameEnded += (sender, args) => capturedWinner = args.winner; _target.Start(); Check.That(capturedWinner).IsEqualTo(_fakeComputer); } [Theory] [InlineData(true, false, true)] // Joueur gagne [InlineData(false, true, false)] // Ordinateur gagne [InlineData(false, false, null)] // Égalité (les deux faux) public void Play_Should_Return_Correct_Winner(bool playerWins, bool computerWins, bool? expectedPlayerWins) { var fakePlayerAction = A.Fake(); var fakeComputerAction = A.Fake(); A.CallTo(() => fakePlayerAction.Name).Returns("Pierre"); A.CallTo(() => fakeComputerAction.Name).Returns("Ciseaux"); A.CallTo(() => fakePlayerAction.ToWin(fakeComputerAction)).Returns(playerWins); A.CallTo(() => fakeComputerAction.ToWin(fakePlayerAction)).Returns(computerWins); A.CallTo(() => _fakePlayer.Play()).Returns(fakePlayerAction); A.CallTo(() => _fakeComputer.Play()).Returns(fakeComputerAction); (string, string)? capturedChoices = null; _target.TurnStarted += (sender, args) => capturedChoices = args; // Act - Appeler Play via réflexion car c'est privé var playMethod = typeof(PierrePapierCiseauxGame) .GetMethod("Play", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var result = (IPlayer?)playMethod?.Invoke(_target, null); Check.That(capturedChoices?.Item1).IsEqualTo("Pierre"); Check.That(capturedChoices?.Item2).IsEqualTo("Ciseaux"); if (expectedPlayerWins == true) Check.That(result).IsEqualTo(_fakePlayer); else if (expectedPlayerWins == false) Check.That(result).IsEqualTo(_fakeComputer); else Check.That(result).IsNull(); } [Fact] public void Start_Should_Increment_Score_When_There_Is_A_Winner() { A.CallTo(() => _fakePlayer.Score).ReturnsNextFromSequence(0, 1, 2); // S'arrête à 2 A.CallTo(() => _fakeComputer.Score).Returns(0); var fakePlayerAction = A.Fake(); var fakeComputerAction = A.Fake(); A.CallTo(() => fakePlayerAction.ToWin(fakeComputerAction)).Returns(true); A.CallTo(() => fakeComputerAction.ToWin(fakePlayerAction)).Returns(false); A.CallTo(() => _fakePlayer.Play()).Returns(fakePlayerAction); A.CallTo(() => _fakeComputer.Play()).Returns(fakeComputerAction); IPlayer? turnWinner = null; _target.TurnEnded += (sender, args) => turnWinner = args.winner; A.CallTo(() => _fakePlayer.Score).Returns(0); A.CallTo(() => _fakeComputer.Score).Returns(0); A.CallTo(() => _fakePlayer.IncrementScore()) .Invokes(() => A.CallTo(() => _fakePlayer.Score).Returns(1)); // Exécuter un seul tour var playMethod = typeof(PierrePapierCiseauxGame) .GetMethod("Play", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var winner = (IPlayer?)playMethod?.Invoke(_target, null); if (winner != null) winner.IncrementScore(); Check.That(winner).IsEqualTo(_fakePlayer); A.CallTo(() => _fakePlayer.IncrementScore()).MustHaveHappenedOnceExactly(); } [Fact] public void Start_Should_Not_Increment_Score_On_Draw() { var fakePlayerAction = A.Fake(); var fakeComputerAction = A.Fake(); // Égalité : les deux retournent false A.CallTo(() => fakePlayerAction.ToWin(fakeComputerAction)).Returns(false); A.CallTo(() => fakeComputerAction.ToWin(fakePlayerAction)).Returns(false); A.CallTo(() => _fakePlayer.Play()).Returns(fakePlayerAction); A.CallTo(() => _fakeComputer.Play()).Returns(fakeComputerAction); var playMethod = typeof(PierrePapierCiseauxGame) .GetMethod("Play", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var winner = (IPlayer?)playMethod?.Invoke(_target, null); Check.That(winner).IsNull(); A.CallTo(() => _fakePlayer.IncrementScore()).MustNotHaveHappened(); A.CallTo(() => _fakeComputer.IncrementScore()).MustNotHaveHappened(); } [Fact] public void Start_Should_Raise_TurnEnded_After_Each_Round() { A.CallTo(() => _fakePlayer.Score).ReturnsNextFromSequence(0, 1, 2, 3); // 3 tours A.CallTo(() => _fakeComputer.Score).Returns(0); var fakeAction = A.Fake(); A.CallTo(() => fakeAction.ToWin(A._)).Returns(true); // Joueur gagne toujours A.CallTo(() => _fakePlayer.Play()).Returns(fakeAction); A.CallTo(() => _fakeComputer.Play()).Returns(fakeAction); var turnEndedCount = 0; _target.TurnEnded += (sender, args) => turnEndedCount++; _target.Start(); Check.That(turnEndedCount).IsEqualTo(3); } [Fact] public void Start_Should_Raise_TurnStarted_Before_Each_Round() { A.CallTo(() => _fakePlayer.Score).ReturnsNextFromSequence(0, 1, 2, 3); A.CallTo(() => _fakeComputer.Score).Returns(0); var fakeAction = A.Fake(); A.CallTo(() => fakeAction.Name).Returns("TestAction"); A.CallTo(() => _fakePlayer.Play()).Returns(fakeAction); A.CallTo(() => _fakeComputer.Play()).Returns(fakeAction); var turnStartedCount = 0; _target.TurnStarted += (sender, args) => turnStartedCount++; _target.Start(); Check.That(turnStartedCount).IsEqualTo(3); } [Fact] public void Play_Should_Throw_When_Action_Is_Not_IActionPpc() { var invalidAction = A.Fake(); // Pas IActionPpc A.CallTo(() => _fakePlayer.Play()).Returns(invalidAction); A.CallTo(() => _fakeComputer.Play()).Returns(A.Fake()); var playMethod = typeof(PierrePapierCiseauxGame) .GetMethod("Play", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); Check.ThatCode(() => playMethod?.Invoke(_target, null)) .Throws(); } } }