Unit testing: replacing dependencies

The point of unit testing is to test classes in isolation. This presents a problem when the class has dependencies. These dependencies must be replaced somehow.

namespace SpaceGame
{
    public class Level
    {
        private IEnumerable<IEnemy> enemies;

        public Level(params IEnemy[] enemies)
        {
            this.enemies = enemies;
        }

        public bool Cleared
        {
            get { return !enemies.Any(e => e.Alive); }
        }

        public void Shoot(int damage)
        {
            damage = damage / enemies.Count();
            foreach (var enemy in enemies)
            {
                enemy.Hit(damage);
            }
        }
    }
}

Dependency injection gives an opportunity to make those replacements. The dependencies are passed to the class instead of the class creating them itself. And by using interfaces the dependencies can be replaced with something else.

namespace SpaceGame.UnitTests
{
    [TestFixture]
    public class LevelTests
    {
        [Test]
        public void OneEnemyNotAlive_IsCleared()
        {
            var enemy = Substitute.For<IEnemy>();
            enemy.Alive.Returns(false);

            Level level = new Level(enemy);

            Assert.IsTrue(level.Cleared);
        }

        [Test]
        public void Shoot_TwoEnemies_DealsHalfDamageToEach()
        {
            var enemy1 = Substitute.For<IEnemy>();
            var enemy2 = Substitute.For<IEnemy>();

            Level level = new Level(enemy1, enemy2);
            level.Shoot(100);

            enemy1.Received().Hit(50);
            enemy2.Received().Hit(50);
        }
    }
}

Isolation frameworks provides a convenient way to create replacements for dependencies. The replacements can be configured to behave as needed for the test. They can also be used to check that they are called appropriately during the test. There are many isolation frameworks available for .NET. This example uses NSubstitute.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s