<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>Moq</title><link>http://blogs.wankuma.com/masaru/category/2247.aspx</link><description>Moq</description><managingEditor>まさる（高野 将、TAKANO Sho）</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>まさる（高野 将、TAKANO Sho）</dc:creator><title>Moq探訪～その２～：Mockライブラリを使うと何が嬉しいのか</title><link>http://blogs.wankuma.com/masaru/archive/2010/12/06/195522.aspx</link><pubDate>Mon, 06 Dec 2010 05:52:00 GMT</pubDate><guid>http://blogs.wankuma.com/masaru/archive/2010/12/06/195522.aspx</guid><wfw:comment>http://blogs.wankuma.com/masaru/comments/195522.aspx</wfw:comment><comments>http://blogs.wankuma.com/masaru/archive/2010/12/06/195522.aspx#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://blogs.wankuma.com/masaru/comments/commentRss/195522.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/masaru/services/trackbacks/195522.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://blogs.wankuma.com/masaru/archive/2010/12/03/195469.aspx"&gt;Moq探訪～その１～：Moqとは何か？Mockとは何か？そしてMockの生成 #adcjcs&lt;/a&gt;に続く第２回目。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;前回はMockとは何か？Moqとは何か？Moqを使ったMockオブジェクトの作成方法について紹介しました。&lt;/p&gt; &lt;p&gt;今回は、先に進む前になぜMockライブラリを使うのか、という話をしようと思います。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;従来のMockオブジェクト作成方法&lt;/h3&gt; &lt;p&gt;今のように便利なMockライブラリができる前も、「Mock」という考えはありました。その実現方法は、&lt;/p&gt; &lt;p&gt;&lt;strong&gt;サブクラス化して、それぞれのメソッドをオーバーライドする&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;または&lt;/p&gt; &lt;p&gt;&lt;strong&gt;interfaceを実装し、それぞれのメソッドを記述する&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;というものでした。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;例を次に示します。&lt;/p&gt; &lt;p&gt;・Mock対象interface&lt;/p&gt; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0835d84c-ee71-4025-82ec-b95c818de939" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public interface IMyInterface
{
  void doSomething();
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;・Mockクラス&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:dcf2d347-7217-45c5-ba2e-07daf7b35df4" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class MyMock : IMyInterface
{
  public void doSomething()
  {
    // 偽装した処理
  }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;・Mockの使用方法&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ad8cd46a-40c4-4a1f-81c9-6019337d9296" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;class Program
{
  static void Main(string[] args)
  {
    // Mockオブジェクトの作成
    var mock = new MyMock();

    // Mockの使用
    mock.doSomething();
  }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;従来の方法の問題&lt;/h3&gt;
&lt;p&gt;サブクラスまたは実装クラスを使ってMockを作成する方法には、大きく２つの問題があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Mock対象のメソッドが多い場合、Mockクラスのコードが膨大になる。 
&lt;li&gt;偽装したい処理ごとにいくつもMockクラスを作る必要がある。&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.巨大なMockコード&lt;/h4&gt;
&lt;p&gt;上で説明したような、メソッドが１つだけのようなinterfaceなら良いのですが、多くのメソッドを持つinterfaceを偽装する場合、そのすべてのメソッドを実装しなければなりません。&lt;/p&gt;
&lt;p&gt;したがって、偽装したいメソッド以外にも、余計なコードが必要です。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;以下に、IListインターフェースの例を示します。&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:7e0d7d4a-6618-4e3c-a1c3-0e869c25828a" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public class MyList : IList
{

  public int Add(object value)
  {
    return 0;
  }

  public void Clear()
  {
  }

  public bool Contains(object value)
  {
    return false;
  }

  public int IndexOf(object value)
  {
    return 0;
  }

  public void Insert(int index, object value)
  {
  }

  public bool IsFixedSize
  {
    get { return true; }
  }

  public bool IsReadOnly
  {
    get { return true; }
  }

  public void Remove(object value)
  {
  }

  public void RemoveAt(int index)
  {
  }

  private object[] objects;
  public object this[int index]
  {
    get
    {
      return objects[index];
    }
    set
    {
      objects[index] = value;
    }
  }

  public void CopyTo(Array array, int index)
  {
  }

  // このプロパティだけ偽装したい
  public int Count
  {
    get { return 0; }
  }

  public bool IsSynchronized
  {
    get { return false; }
  }

  public object SyncRoot
  {
    get { return null; }
  }

  public IEnumerator GetEnumerator()
  {
    return objects.GetEnumerator();
  }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;2.複数のMockクラスが必要&lt;/h4&gt;
&lt;p&gt;偽装したい処理が少なければまだよいのですが、0を返す場合、1を返す場合、例外を発生させる場合、・・・と様々な処理を偽装したい場合、その処理ごとにMockクラスを作成する必要があります。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;以下に例を示します。&lt;/p&gt;
&lt;p&gt;・Mock対象inteface&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:4972e42e-4057-4036-b6e3-42f709884588" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public interface IMyInterface
{
  int GetCount();
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;・Mockクラス&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:6525bd87-c38a-4be6-8235-89e1cc8664ad" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;// 0を返すMock
public class MyMockReturnZero : IMyInterface
{
  public int GetCount()
  {
    return 0;
  }
}

// 1を返すMock
public class MyMockReturnOne : IMyInterface
{
  public int GetCount()
  {
    return 1;
  }
}

// 例外をthrowするMock
public class MyMockThrowException : IMyInterface
{
  public int GetCount()
  {
    throw new Exception("例外処理の偽装");
  }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Mockライブラリを使った解決&lt;/h3&gt;
&lt;p&gt;Mockライブラリを使うと、上記の問題を解決し、コード量を大幅に削減することができます。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;1.Mockオブジェクト専用の実装クラスが不要&lt;/h4&gt;
&lt;p&gt;前回紹介したように、Moqを使ってMockオブジェクトを作成するには、これだけです。&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:fc81cf76-decf-4534-a547-8e38e1233d05" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;// Mockの作成
var mock = new Mock&amp;lt;IMyInterface&amp;gt;();

// Mockオブジェクトの取得
var obj = mock.Object;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;2.複数の処理を偽装したMockの作成が容易&lt;/h4&gt;
&lt;p&gt;Moqを使って複数の処理を偽装するには、次のように書きます。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;・Mock作成コード&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ee15c7b1-4ac2-4cf0-b6df-cbad3f4509c9" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c"&gt;public static void Main(string[] args)
{
  // Mockの作成
  var mock = new Mock&amp;lt;IMyInterface&amp;gt;();

  // 0を返す
  mock.Setup(m =&amp;gt; m.GetCount()).Returns(0);
  Console.WriteLine(mock.Object.GetCount());

  // 1を返す
  mock.Setup(m =&amp;gt; m.GetCount()).Returns(1);
  Console.WriteLine(mock.Object.GetCount());

  // 例外を発生させる
  mock.Setup(m =&amp;gt; m.GetCount()).Throws(new Exception("例外を発生させる"));
  try
  {
    mock.Object.GetCount();
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
  }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;・実行結果&lt;/p&gt;
&lt;p&gt;&lt;a href="http://masaru.wankuma.com/img/blogimg/MoqMock_44FB/image.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://masaru.wankuma.com/img/blogimg/MoqMock_44FB/image_thumb.png" width="633" height="333"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;まとめ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MockライブラリがなくてもMockを作成することは可能。 
&lt;ul&gt;
&lt;li&gt;ただし、かなりコード量が多くなる。&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Mockライブラリを使うことで、シンプルにMockを記述できるようになる。 
&lt;ul&gt;
&lt;li&gt;コード量を大幅に削減できる。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;次回以降の予定&lt;/h3&gt;
&lt;p&gt;Mockライブラリの利点を紹介したところで、次からは実際にいろいろなMoqの機能を紹介していきます。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/masaru/aggbug/195522.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>