bugfix> c# > 投稿

私はこれについて正しい方法で行っていますか?もしそうなら、私はそれを正しく理解していますか?私は少し混乱しています。

私のプロジェクトは3つの異なるレイヤーでセットアップされています。 UIレイヤー、ビジネスレイヤー、およびデータアクセスレイヤー。ビジネスレイヤーとデータアクセスレイヤーは、どちらもインターフェイスから構築されています。

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()呼び出しで返すように設定したものは何でも返すだけです。 6ではなく、Returns()に3を入力すると、失敗します。

何か間違ったことを理解しているに違いありません。それ以外の場合、何を返すかを伝えている場合、実際に関数をテストしていますか?

回答 1 件
  • さて、インターフェース 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());
        }
    }
    
    

あなたの答え