Jun 3, 2014
4 mins read
當系統利用介面完成物件來隔離外部物件之後,為了方便測試通常會寫一些假的物件來抽換 但功能越來越多之後,測試的假類別也越多,檔案不好管理 這時後可以讓Moq利用反射的方式讓我們很容易地新增假物件 Moq只能模擬公開的介面,如果是繼承的類別則需要Virtual才能模擬
要使用Moq很簡單,利用NuGet安裝套件就行了
](http://1.bp.blogspot.com/-cwTzcXKv6l0/U408MjPlOYI/AAAAAAAABXU/yxksMr1XfO8/s1600/01.Moq.png)
public interface IFoo
{
void F1();
int F2();
int F3(int x);
event EventHandler<object> MyEvent;
}
首先建立一個IFoo型別的Mock物件 在建構式中可以指定MockBehavior來設定模擬物件的程度 Strict是限制需要完整模擬物件,Loose則不需要 預設為Default,也就是Loose
private Mock<IFoo> mock;
[TestInitialize]
public void MyTestInitialize()
{
this.mock = new Mock<IFoo>();
}
一開始先用沒有回傳值的函式當例子,就先不做更多的設定 直接使用Mock物件的Object屬性取得模擬的假物件就可以使用了 這裡用Verify和Times來檢查該函式的呼叫次數
[TestMethod]
public void TestMethod1()
{
Mock<IFoo> foo = new Mock<IFoo>();
foo.Object.F1();
foo.Verify(x => x.F1(), Times.Once());
}
再來用一個有回傳值的函式當例子,所以再加上回傳值的設定 這裡的意思是呼叫F2函式的時後,總是回傳123的值回來
[TestMethod]
public void TestMethod2()
{
Mock<IFoo> foo = new Mock<IFoo>();
foo.Setup(x => x.F2()).Returns(123);
Assert.AreEqual(123, foo.Object.F2());
}
函式中的參數可以透過It物件來設定 這裡的意思是只要傳入int型別的參數,就回傳456的值
[TestMethod]
public void TestMethod3()
{
Mock<IFoo> foo = new Mock<IFoo>();
foo.Setup(x => x.F3(It.IsAny<int>())).Returns(456);
Assert.AreEqual(456, foo.Object.F3(1));
}
[TestMethod]
public void TestMethod4()
{
int counter = 0;
Mock<IFoo> foo = new Mock<IFoo>();
foo.Setup(x => x.F1()).Callback(() => counter++);
foo.Object.F1();
Assert.AreEqual(1, counter);
}
[TestMethod]
[ExpectedException(typeof(Exception))]
public void TestMethod5()
{
Mock<IFoo> foo = new Mock<IFoo>();
foo.Setup(x => x.F1()).Throws(new Exception());
foo.Object.F1();
}
[TestMethod]
public void TestMethod6()
{
Mock<IFoo> foo = new Mock<IFoo>();
foo.Raise(x => x.MyEvent += (s, a) => { Console.WriteLine(a); }, 123);
}
參考資料 Moq Quickstart
Sharing is caring!