天天看點

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()

MOQ TIP1:簡介加基礎

本篇代碼下載下傳:

ConsoleApplication20110812.rar
MOQ TIP1:簡介加基礎

本文基于

Creative Commons Attribution 2.5 China Mainland License

釋出,歡迎轉載,演繹或用于商業目的,但是必須保留本文的署名

http://www.cnblogs.com/luminji

(包含連結)。如您有任何疑問或者授權方面的協商,請給我留言。

繼續閱讀