Модульное тестирование бизнес-логического интерфейса - PullRequest
0 голосов
/ 08 июня 2018

Правильно ли я поступаю?И если да, правильно ли я понимаю?Я немного запутался.

Мой проект состоит из трех разных слоев.Уровень пользовательского интерфейса, бизнес-уровень и уровень доступа к данным.Бизнес-уровень и уровень доступа к данным построены на основе интерфейсов.

Я пытаюсь написать модульные тесты, используя NUnit и Moq.

Вот мой пример.Я хочу протестировать GetSum (int x, int y), которая является простой функцией, которая просто возвращает x + y.Эта функция существует в CalculatorLogic и реализует ICalculatorLogic.

public class CalculatorLogic : ICalculatorLogic
{
    public int GetSum(int x, int y)
    {
        return x + y;
    }
}

Теперь вот как я пытаюсь написать UnitTest.

[TestFixture]
public class CalculatorLogicTests
{
    Mock<ICalculatorLogic> calculatorLogicMock;
    ICalculatorLogic calculatorLogic;

    public CalculatorLogicTests()
    {
        calculatorLogicMock = new Mock<ICalculatorLogic>();

        // now i need to do this setup, right?
        calculatorLogicMock.Setup(x => x.GetSum(It.IsAny<int>(), It.IsAny<int>())).Returns(6);

        calculatorLogic = calculatorLogicMock.Object;
    }

    [Test]
    public void GetSum_Test()
    {
        int expectedResult = 3 + 3;

        var sum = calculatorLogic.GetSum(3, 3);
        Assert.AreEqual(sum, expectedResult);
    }
}

Теперь вышесказанное проходит.Он работает, и он получает то, что я ожидаю.Тем не менее, он чувствует себя неправильно.Он просто возвращает все, что я установил для возврата в вызове Setup ().Если бы я поставил 3 в Returns () вместо 6, он потерпел бы неудачу.

Я должен понять, что-то не так.Иначе, действительно ли я проверяю свою функцию, если я говорю, что возвращать?

1 Ответ

0 голосов
/ 11 июня 2018

Хорошо, у вас есть интерфейс ICalculatorLogic и реализация указанного интерфейса CalculatorLogic, для которого вы хотите написать тесты.

Вы используете макет Moq для моделирования зависимостейчто ваш CalculatorLogic не имеет.Вы должны написать что-то вроде этого:

[TestFixture]
public class CalculatorLogicTests
{
    // Our unit under test.
    ICalculatorLogic calculatorLogic;

    [SetUp]
    public void SetUp()
    {
        // This method is called for every [Test] in this class.
        // So let's recreate our CalculatorLogic here so that each
        // test has a fresh instance.
        calculatorLogic = new CalculatorLogic();
    }

    [Test]
    public void GetSum_WithTwoIntegers_ReturnsTheirSum()
    {
        // Arrange
        int expectedResult = 3 + 3;

        // Act
        var sum = calculatorLogic.GetSum(3, 3);

        // Assert
        Assert.AreEqual(sum, expectedResult);
    }
}

Теперь предположим, что вы хотите, чтобы ваш GetSum регистрировал параметры, с которыми он вызывается.Вы можете создать интерфейс логгера следующим образом:

public interface ILogger {
    void Log(int x, int y);
}

Затем вы помещаете его как зависимость, требуя его в конструкторе вашего CalculatorLogic класса:

public class CalculatorLogic : ICalculatorLogic
{
    private readonly ILogger logger;

    // Now we have a dependency on ILogger!
    public CalculatorLogic(ILogger l) {
        logger = l;
    }

    public int GetSum(int x, int y)
    {
        // Let's log those numbers!
        logger.Log(x, y);
        return x + y;
    }
} 

Тогда вы можетенапишите свои тесты так (используя Moq):

[TestFixture]
public class CalculatorLogicTests
{
    // This guy we want to test.
    ICalculatorLogic calculatorLogic;

    // Our mock!
    Mock<ILogger> loggerMock;

    [SetUp]
    public void SetUp()
    {
        // Create the logger mock!
        loggerMock = new Mock<ILogger>();

        // Inject the logger into our CalculatorLogic!
        calculatorLogic = new CalculatorLogic(loggerMock.Object);
    }

    [Test]
    public void GetSum_WithTwoIntegers_ShouldCallLogger()
    {
        // Arrange
        int expectedResult = 3 + 3;

        // Act
        var sum = calculatorLogic.GetSum(3, 3);

        // Assert
        Assert.AreEqual(sum, expectedResult);

        // Verify that the logger's Log method was called once with x = 3 and y = 3.
        loggerMock.Verify(logger => logger.Log(It.Is<int>(x => x == 3), It.Is<int>(y => y == 3)), Times.Once());
    }
} 
...