1

I am trying to create a simple setup for xUnit. At the moment, the function does not access to database.

So, here is my structure: I have 2 projects in my solution. First is my class library which is going to be the function to be used by the callee. The function is plus and minus 2 numbers for simplicity reason.

namespace XUnitSample.ClassLib.Interfaces
{
    public interface ICal
    {
        int Add(int num1, int num2);
        int Minus(int num1, int num2);
    }
}

namespace XUnitSample.ClassLib
{
    public class Cal : ICal
    {
        public int Add(int num1, int num2) => num1 + num2;        
        public int Minus(int num1, int num2) => num1 - num2;        
    }
}

and the second project is the xUnit test project

namespace XUnitSample.Lib
{

public class CalTest
{
    [Fact]
    public void Add_Add2Numbers()
    {
        var mock = new Mock<ICal>();
        mock.Setup(x => x.Add(1, 1)).Returns(2);
    }

    [Theory]
    [InlineData(1,2,3)]
    [InlineData(1, 1, 2)]
    [InlineData(1, 0, 1)]
    public void Add_Add2Numbers_Theory(int num1, int num2, int expected)
    {
        var result = new Cal().Add(num1, num2);
        Assert.Equal(expected, result);
    }

    [Fact]
    public void Minus_Minus2Numbers()
    {
        var mock = new Mock<ICal>();
        mock.Setup(x => x.Minus(1, 1)).Returns(0);
    }
}
}

All 3 unit test can be run successfully. Any comments on this structure and good practices?

  • 2
    I'm not an xUnit expert, but your first and third tests don't actually seem to be tests, in that they never assert anything. More generally, you should never be mocking the unit you're testing, because then you're not testing your code. – Philip Kendall Jun 14 at 7:59
  • You’re testing class Cal. Cal has no dependencies on other classes. Therefor you don’t need to mock anything to test class Cal. – Rik D Jun 14 at 9:55
2

When I write a unit test, I use the 'AAA' pattern: Arrange, Act, Assert. For your second unit test, it would look like this:

    [Theory]
    [InlineData(1,2,3)]
    [InlineData(1, 1, 2)]
    [InlineData(1, 0, 1)]
    public void Add_Add2Numbers_Theory(int num1, int num2, int expected)
    {
        // Arrange
        var cal = new Cal();

        // Act
        var result = cal.Add(num1, num2);

        // Assert
        Assert.Equal(expected, result);
    }

That way, you have a clear separation of the setup, the execution and the checks in the unit test. More on this subject can be found on numerous sites, like this one: Understand AAA in Unit Testing.

In the first and third unit test, you are using 'mocking' wrong. Mocking is used to replace dependencies. In this case, the ICal interface is not a dependency of the Cal class, it is just the interface that the Cal class is implementing. So there is no use in mocking it.

Mocking comes in place when your Cal class depends on some other class or library, for example a "CalculationEngine". Then the constructor of the Cal class looks like this:

    public Cal(ICalculationEngine calculationEngine)
    {
        _calculationEngine = calculationEngine;
    }

In such case, when you test the Cal class, you need to mock the CalculationEngine. And then, you can control the behaviour of this dependency by supplying specific setups for its methods.

An example:

    namespace XUnitSample.ClassLib.Interfaces
    {
        public interface ICalculationEngine
        {
            int Add(int num1, int num2);
            int Minus(int num1, int num2);
        }
    }

    namespace XUnitSample.ClassLib
    {
        public class Cal
        {
            private readonly ICalculationEngine _calculationEngine;

            public Cal(ICalculationEngine calculationEngine)
            {
                _calculationEngine = calculationEngine;
            }

            public int Add(int num1, int num2)
            {
                return _calculationEngine.Add(num1, num2);
            }

            public int Minus(int num1, int num2)
            {
                return _calculationEngine.Minus(num1, num2);
            }
        }
    }
    namespace XUnitSample.Lib
    {
        public class CalTest
        {
            [Fact]
            public void Add_Add2Numbers()
            {
                // Arrange
                var mock = new Mock<ICalculationEngine>();
                mock.Setup(x => x.Add(1, 1)).Returns(2);

                var cal = new Cal(mock.Object);

                // Act
                var result = cal.Add(1,1);

                // Assert
                Assert.Equal(result, 2)
            }
        }
    }
| improve this answer | |
  • Thanks. So why Cal should use ICalculationEngine as constructor and not through implementation (Cal : ICalculationEngine)? – Steve Jun 14 at 9:21
  • 1
    It was just an example. In real applications, the dependency might be an WebAPI, or a database. These are difficult to use in a unit test, so mocking them makes sense. In this case, I only wanted to show you the difference between implementing an interface, and having a dependency on another class. – Frits Jun 14 at 9:24
  • For Add_Add2Numbers_Theory method, I shall do the same like other methods, right? // Arrange var mock = new Mock<ICal>(); mock.Setup(x => x.Add(num1, num2)).Returns(expected); var cal = new Cal(mock.Object); – Steve Jun 14 at 9:29
  • 1
    Yes, you can do that, but be aware that this is not a real-world scenario. – Frits Jun 14 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.