public void Attack_ShouldThrowInvalidOperationExceptionWhenTheHeroHasNoHealth()
        {
            //Arrange
            IHero hero     = new HeroBuilder().WithHealth(0).Build();
            IHero opponent = new HeroBuilder().Build();

            //Act + Assert
            Assert.That(() => hero.Attack(opponent), Throws.InstanceOf <InvalidOperationException>());
        }
        public void Attack_SuperMode_ShouldAttackOpponentWithDoubleStrength()
        {
            //Arrange
            IHero        hero         = new HeroBuilder().WithSuperModeLikeliness(1.0f).Build();
            Mock <IHero> opponentMock = new HeroMockBuilder().Build();

            //Act
            hero.Attack(opponentMock.Object);

            //Assert
            opponentMock.Verify(opponent => opponent.DefendAgainstAttack(hero.Strength * 2), Times.Once,
                                $"Should call 'DefendAgainstAttack' of opponent with strength {hero.Strength * 2}.");
        }
        private void AssertSuperModeLikelinessForAttack(float superModeLikeliness)
        {
            IHero hero = new HeroBuilder().WithSuperModeLikeliness(superModeLikeliness).Build();

            int numberOfAttacks       = 200;
            int numberOfNormalAttacks = 0;
            int numberOfSuperAttacks  = 0;

            for (int i = 0; i < numberOfAttacks; i++)
            {
                Mock <IHero> opponentMock = new HeroMockBuilder().Build();
                opponentMock.Setup(opponent => opponent.DefendAgainstAttack(It.IsAny <int>()))
                .Callback((int attackStrength) =>
                {
                    if (attackStrength == hero.Strength)
                    {
                        numberOfNormalAttacks++;
                    }
                    else if (attackStrength == hero.Strength * 2)
                    {
                        numberOfSuperAttacks++;
                    }
                });
                hero.Attack(opponentMock.Object);
            }

            Assert.That(numberOfNormalAttacks, Is.GreaterThan(0),
                        $"Out of {numberOfAttacks} attacks, no normal attack happened. That is not random enough.");
            Assert.That(numberOfSuperAttacks, Is.GreaterThan(0),
                        $"Out of {numberOfAttacks} attacks, no supermode attack happened. That is not random enough.");
            Assert.That(numberOfSuperAttacks + numberOfNormalAttacks, Is.EqualTo(numberOfAttacks),
                        $"The amount of normal attacks ({numberOfNormalAttacks}) " +
                        $"added with the number of supermode attacks ({numberOfSuperAttacks}) " +
                        $"should be equal to the total number of attacks ({numberOfAttacks}).");
            double actualSuperMode = numberOfSuperAttacks / (double)numberOfAttacks;

            Assert.That(actualSuperMode, Is.EqualTo(hero.SuperModeLikeliness).Within(0.15),
                        $"After {numberOfAttacks} attacks the supermode likeliness seems to be around {Convert.ToInt32(actualSuperMode * 100)}%. " +
                        $"It should be around {Convert.ToInt32(hero.SuperModeLikeliness * 100)}%.");
        }