Billpeng Space

技术源自生活
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Moq是无法直接模拟静态方法的,解决方式有两种:

1、需要修改正式代码,在源代码中建一个新的方法把静态方法包起来,调用的时候源代码调用时调用新方法而不是原来的静态方法。

在测试的时候,Mock掉这个新的方法,以达到模拟的目的

原来:

    public class FormatClass
    {
        public static string FormatDate(DateTime date)
        {
            return date.ToString("yyyyMMdd");
        }
    }

    public class DoClass
    {
        public void Do()
        {
            var dateString = FormatClass.FormatDate(DateTime.Now);
            Console.WriteLine(dateString);
        }
    }

    [TestClass]
    public class Test
    {
        [TestMethod]
        public void MyTest()
        {
            var mock = new Mock<DoClass>();
            mock.Object.Do();
        }
    }

替换后:

   public class FormatClass
    {
        public static string FormatDate(DateTime date)
        {
            return date.ToString("yyyyMMdd");
        }
    }

    public class DoClass
    {
        public void Do()
        {
            var dateString = DefineFormatDate(DateTime.Now);
            Console.WriteLine(dateString);
        }

        //包装一个方法用于Mock
        public virtual string DefineFormatDate(DateTime date)
        {
            return FormatClass.FormatDate(date);
        }
    }

    [TestClass]
    public class Test
    {
        [TestMethod]
        public void MyTest()
        {
            var mock = new Mock<DoClass>();
            //Mock方法
            mock.Setup(a => a.DefineFormatDate(It.IsAny<DateTime>())).Returns("mock content");
            mock.Object.Do();
        }
    }

2、由于Mircosoft Fakes框架可以使用Shim模拟静态方法,那么我们可以将Moq和Fakes配合起来,用Fakes模拟静态方法,其他判断还用Moq

[TestClass]
    public class Test
    {
        [TestMethod]
        public void MyTest()
        {
            var mock = new Mock<DoClass>();
            //未Shim之前
            mock.Object.Do();

            using (ShimsContext.Create())
            {
                DFYYDream.Infrastructure.Fakes.ShimPinYinConvert.ConvertToPinYinStringBoolean = (String, Boolean) =>
                {
                    return "mock content";
                };

                //已经Shim之后
                mock.Object.Do();
            }

            //moq可以正常判断
            mock.Verify(a => a.DoOther2(), Times.AtLeast(2));
        }
    }

    public class DoClass
    {
        public void Do()
        {
            //一个中文转拼音的静态方法
            var py = PinYinConvert.ConvertToPinYin("你好", false);
            DoOther(py);
            DoOther2();
        }

        public void DoOther(string py)
        {
            Console.WriteLine(py);
        }

        public virtual void DoOther2()
        {
        }
    }

测试结果:

NIHAO
mock content

代码里的DFYYDream.Infrastructure.Fakes命名空间,是通过右击“引用”里的程序集的名称后,选择“添加Fakes程序集”自动生成的。

 总结:

第一种方法不需要引入Fakes,但需要修改调用处的源代码

第二种方法不需要改把源代码,只需要在测试处模拟即可,但需要引入Fakes