.net core unit test JustMock first article

Introduced in front of NUnit unit testing framework that can help us build a very good test, test our code is correct. But this is not enough, sometimes our business is relatively heavy, depend on other classes. Based on the principle of isolation tests, we do not want to rely on other classes affect our testing objectives. Mock this time it is very important. Of course there are other factors that we have to make Mock objects, such as configuration files, DB and so on.

Mock technology provides a lot of tools: Moq, NSubstitute, RhinoMocks, TypeMock , JustMock and so on. Free open source tool functional limitations, like Moq, grassroots column of the blog is well written. I chose JustMock, the paid version can use the advanced features.

JustMock start

Installation JustMock, from the official website to download , installed by default.

Add Telerik.JustMock.dll references in the installation directory, by default: C: \ Program Files (x86) \ Progress \ Telerik JustMock \ Libraries.

Using Advanced Features open
image

Why Mock

We need to look at a method of testing:

        /// <summary>
        /// 转账
        /// </summary>
        /// <param name="accountA"></param>
        /// <param name="accountB"></param>
        /// <param name="money"></param>
        /// <returns></returns>
        public double TransferAccounts(BankAccount accountA, BankAccount accountB, double money)
        {
            double transferLimit = 50000.0;//转账最高限制
            try
            {
                var balanceA = accountA.DrawMoney(money);
                accountB.SaveMoney(money);
                return balanceA;
            }
            catch (Exception ex)
            {
                throw new Exception($"转账失败,{ex.Message}");
            }
        }

Test logic of this method, only the following code on it:

        private BankAccount bankAccountA;
        private BankAccount bankAccountB;
        [SetUp]
        public void Setup()
        {
            bankAccountA = new BankAccount(1000);
            bankAccountB = new BankAccount(1000);
        }

        [Test]
        public void Transfer_Test()
        {
            IBankService bankService = new BankService();
            bankService.TransferAccounts(bankAccountA, bankAccountB, 500);
            Assert.AreEqual(500, bankAccountA.GetBalance());
            Assert.AreEqual(1500, bankAccountB.GetBalance());
        }

However, if the logic transfers the changed needs to judge whether or exceeds the date limit, the user must transfer the total amount obtained from the database or other means, it becomes possible codes like this:

        private readonly IBankLimitDao _bankLimitDao;//获取限制条件的类

        public BankService(IBankLimitDao bankLimitDao)
        {
            _bankLimitDao = bankLimitDao;
        }

        /// <summary>
        /// 转账
        /// </summary>
        /// <param name="accountA"></param>
        /// <param name="accountB"></param>
        /// <param name="money"></param>
        /// <returns></returns>
        public double TransferAccounts(BankAccount accountA, BankAccount accountB, double money)
        {
            double transferLimit = 50000.0;//转账最高限制
            try
            {
                //判断A是否能转账
                var total = _bankLimitDao.TotalTransferTotal(accountA.AccountId);//获得限制金额
                if (total >= transferLimit)
                {
                    throw new Exception($"超过当日转账限额{transferLimit}");
                }
                var balanceA = accountA.DrawMoney(money);
                accountB.SaveMoney(money);
                return balanceA;
            }
            catch (Exception ex)
            {
                throw new Exception($"转账失败,{ex.Message}");
            }
        }

This time again the real object to test a little trouble. According to the principle of isolation, we do not want to test TotalTransferTotalthe method in logic and its validity, it should be tested elsewhere. Mock this time it is important, we can simulate the object and give it a proper value, it "right" to perform.

Therefore, the test code becomes like this:

        [Test]
        public void Transfer_Test()
        {
            var bankLimit = Mock.Create<IBankLimitDao>();//模拟对象
            Mock.Arrange(() => bankLimit.TodalDrawTotal(Arg.IsAny<string>())).Returns(500);//设定一个返回值
            IBankService bankService = new BankService(bankLimit);
            bankService.TransferAccounts(bankAccountA, bankAccountB, 500);
            Mock.Assert(bankLimit);
            Assert.AreEqual(500, bankAccountA.GetBalance());
            Assert.AreEqual(1500, bankAccountB.GetBalance());
        }

AAA

What is AAA? Arrange, Act and Assert. AAA is a coding unit test mode.

  • Arrange: ready, set the object to be tested.
  • Act: The actual code testing.
  • Assert: Verify results.

A simple example:
This example includes creating mock objects, labeled InOrder (), which means you must call the execution method, and finally Mock.Assert verification.

public interface IFoo 
{ 
    void Submit(); 
    void Echo(); 
} 
[Test]
public void ShouldVerifyCallsOrder()
{
    // Arrange 模拟对象,并且设置条件
    var foo = Mock.Create<IFoo>();

    Mock.Arrange(() => foo.Submit()).InOrder();
    Mock.Arrange(() => foo.Echo()).InOrder();

    // Act 执行代码
    foo.Submit();
    foo.Echo();

    // Assert 验证结果
    Mock.Assert(foo);
} 

When writing test method AAA try to follow the pattern write, you can make the test code more readable.

Mock Behaviors

JustMock in Mock object when there are four different behaviors can be selected.

  • RecursiveLoose Behavior
    default option. Object simulation will not be null object, a recursive call will also create a default object, the default value or null value.
  • Loose Behavior
    In addition to setting value, or Loose objects created will be the default.
  • CallOriginal Behavior
    will use the original analogue object.
  • Strict Behavior
    With this behavior, you must set the value of the mock object, there would be MockExceptionan exception.

The following code shows the different types of results:

        [Test]
        public void Test()
        {
            // Arrange 
            var rlFoo = Mock.Create<FooBase>(Behavior.RecursiveLoose);
            var lFoo = Mock.Create<FooBase>(Behavior.Loose);
            var coFoo = Mock.Create<FooBase>(Behavior.CallOriginal);
            var sFoo = Mock.Create<FooBase>(Behavior.Strict);

            Mock.Arrange(() => rlFoo.GetString("y")).Returns("z");
            Mock.Arrange(() => lFoo.GetString("y")).Returns("z");
            Mock.Arrange(() => coFoo.GetString("y")).Returns("z");
            Mock.Arrange(() => sFoo.GetString("y")).Returns("z");

            // Act 
            var rlactualX = rlFoo.GetString("x"); // 结果:""
            var rlactualY = rlFoo.GetString("y"); // 结果:"z"

            var lactualX = lFoo.GetString("x"); // 结果:null
            var lactualY = lFoo.GetString("y"); // 结果:"z"

            var coactualX = coFoo.GetString("x"); // 结果:"x"
            var coactualY = coFoo.GetString("y"); // 结果:"z"
            var coactualA = coFoo.GetString("a"); // 结果:"a"

            //var sactualX = sFoo.GetString("x"); // 结果:出现异常
            var sactualY = sFoo.GetString("y"); // 结果:"z"  

            var expectedX = "x";
            var expectedY = "z";

            // Assert 
            Assert.AreEqual(expectedX, rlactualX);
            Assert.AreEqual(expectedY, rlactualY);
        }

Benpian to that, the next re-recorded some of the other uses.

Guess you like

Origin www.cnblogs.com/jimizhou/p/11419364.html