• MOQ TIP1:简介加基础


    MOQ来自于http://code.google.com/p/moq/。下载后其实是直接作为DLL被引用的。

    Mock是模拟对象的一种技术。

    它可以用于以下情况:

    ----- 真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)

    ----- 真实对象很难被创建(比如具体的web容器)

    ----- 真实对象的某些行为很难触发(比如网络错误)

    ----- 真实情况令程序的运行速度很慢

    ----- 真实对象有用户界面

    ----- 测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)

    ----- 真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题)

    1:测试返回值

    需要被测试的代码:

        public interface ICounter
        {
            int CountArgs(int a, int b);
        }
    
        public class SampleClass
        {
            private ICounter _counter;
            public SampleClass(ICounter counter)
            {
                _counter = counter;
            }
    
            public int GetResoult()
            {
                return _counter.CountArgs(1, 2) + 3;
            }
        }

    测试代码:

                Mock<ICounter> mock = new Mock<ICounter>();
                mock.Setup(counter => counter.CountArgs(1, 2)).Returns(3);
                SampleClass sample = new SampleClass(mock.Object);
                int re = sample.GetResoult();
                mock.Verify();
                Assert.AreEqual(re, 6);

    2:测试抛出异常

    假设待测试代码为:

        public interface ICounter
        {
            int CountArgs(int a, int b);
        }
    
        public class SampleClass
        {
            private ICounter _counter;
            public SampleClass(ICounter counter)
            {
                _counter = counter;
            }
    
            public int GetResoult()
            {
                return _counter.CountArgs(100, 123) + 3;
            }
        }

    测试代码则为:

                Mock<ICounter> mock = new Mock<ICounter>();
                mock.Setup(arg => arg.CountArgs(100, 123)).Throws(new ArgumentException("参数过大"));
                SampleClass sample = new SampleClass(mock.Object);
                try
                {
                    int re = sample.GetResoult();
                    mock.Verify();
                }
                catch (ArgumentException)
                {
                    return;
                }
                Assert.Inconclusive("error");

    3:一些限制

    MOQ可以直接模拟接口,但是在模拟类的时候,有如下限制:

    类不能是密封的;

    方法要加上虚修饰符;

    不能模拟静态方法(可以通过适配器模式来模拟静态方法);

    其实这些限制中,一般来说我们是不需要模拟类的,但是抽象类还是需要模拟的比较多,比如:

        public abstract class CounterBase
        {
            public abstract int CountArgs(int a, int b);
    
            public int ArgProp { get; set; }
    
            public virtual string GetSomethingVitual()
            {
                return ArgProp.ToString();
            }
    
            public string GetSomethingReal()
            {
                return "abc";
            }
    
        }
    
        public class SampleClass
        {
            private CounterBase _counter;
            public SampleClass(CounterBase counter)
            {
                _counter = counter;
            }
    
            public int GetResult()
            {
                return _counter.CountArgs(1, 2) + 3;
            }
    
            public string GetVitual()
            {
                return _counter.GetSomethingVitual();
            }
    
            public string GetReal()
            {
                return _counter.GetSomethingReal();
            }
        }

    在这里,作为调用者SampleClass来说,由于使用到了CounterBase,所以CounterBase 这个抽象类就是有必要被模拟的。SampleClass演示了调用抽象方法、虚方法、普通方法,运行的结果是:

    ------ Test started: Assembly: TestProject1.dll ------
    
    Test 'TestProject1.ProgramTest.TestReal' failed: Test method TestProject1.ProgramTest.TestReal threw exception: 
    System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: arg => arg.GetSomethingReal()
    	at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo method)
    	at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
    	at Moq.PexProtector.Invoke[T](Func`1 function)
    	at Moq.Mock.Setup[T,TResult](Mock mock, Expression`1 expression, Func`1 condition)
    	at Moq.Mock`1.Setup[TResult](Expression`1 expression)
    	ProgramTest.cs(101,0): at TestProject1.ProgramTest.TestReal()
    
    2 passed, 1 failed, 0 skipped, took 1.32 seconds (MSTest 10.0).

    我们可以看到,前面两个方法都成功,只有那个非虚拟的普通方法失败,信息如下:

    Invalid setup on a non-virtual (overridable in VB) member: arg => arg.GetSomethingReal()

    image

    本篇代码下载:ConsoleApplication20110812.rar

  • 相关阅读:
    软件的一般实现过程
    前端开发所需技能及理解
    前端开发所需技能
    JavaScriptlet和const的使用
    [NOI2013] 向量内积
    [省选联考 2021 A/B 卷] 滚榜
    [提高组集训2021] 模拟赛2
    [省选联考 2021 A 卷] 矩阵游戏
    [省选联考 2021 A/B 卷] 图函数
    [APIO2020] 交换城市
  • 原文地址:https://www.cnblogs.com/luminji/p/2136351.html
Copyright © 2020-2023  润新知