<?xml version="1.0" encoding="Windows-31J"?>

<!--
<!DOCTYPE document SYSTEM "./dtd/document-v10.dtd">
-->

<document>
  <header>
    <title>モック・オブジェクト 対 コンテナ内テスト</title>
    <authors>
      <person name="Vincent Massol" email="vmassol@apache.org"/>
    </authors>
	<translator>平田 正</translator>
  </header>

  <body>

    <s1 title="モック・オブジェクト 対 コンテナ内テスト">
      <note>
        この文章を通じて、モック・オブジェクトを MO と、コンテナ内
        (In-Container)戦略を IC と略記します。

		Throughout this article, we'll use the abbreviations MO for Mock
        Objects and IC for In-Container strategy.
      </note>
      <ul>
        <li>
          <jump anchor="mo_serverside">MO とサーバ側テスト</jump>
        </li>
        <li>
          <jump anchor="mo_example">例</jump>
        </li>
        <li>
          <jump anchor="mo_differences">MO と IC の違い</jump>
        </li>
        <li>
          <jump anchor="mo_conclusion">結論</jump>
        </li>
        <li>
          <jump anchor="mo_resources">MO に関する参考文献</jump>
        </li>
      </ul>
    </s1>

    <anchor id="mo_serverside"/>
    <s1 title="MO とサーバ側テスト">

      <p>
	    MO は Java クラスの単体テストをするための一般的な戦略です。
		Servlet や Filter、Taglib、EJB といったサーバ側コードの単体テストにも、
		そのまま使用することができます。
		MO に関する詳細はオリジナルの文書である
        <link href="http://mockobjects.sourceforge.net/endotesting.html">
        "Endo-Testing : Unit Testing with Mock Objects"</link>
		を参照してください。これだけ見ると、
		MO は Cactus の競合のようにも見えます。
		しかし、この文章の残りの部分では、
		MO は Cactus を置き替えるものではなく、
		実際には Cactus を補完するものであるということを説明します。

        MO is a strategy to unit test java classes in general. As such
        it is also applicable to unit test server side code like Servlets,
        Filters, Taglibs, EJBs, ... See the original article
        <link href="http://mockobjects.sourceforge.net/endotesting.html">
        "Endo-Testing : Unit Testing with Mock Objects"</link> for full details
        on MO. As such it is a challenger to Cactus but we'll see
        in the rest of this article that it is in fact complementary rather than
        a replacement.
      </p>
      <p>
	    MO の目的は、
		周辺オブジェクトから独立した形でメソッドの単体テストを行うことです。
		このため、MO アプローチでは実際のオブジェクトの代わりに、
		それをシミュレートするコピー(モック・オブジェクト)を使って
		周辺オブジェクトを偽装します
		(MO の偽装オブジェクトはスタブとして働き、
		その中でいかなるロジックも実装されないことに注意してください。
		モック・オブジェクトの全ての挙動は単体テスト自身によって制御されます)。
		これにより、周辺環境の影響を受けることなく、
		メソッドの精細な単体テストを行うことが可能になり、
		そのロジックを単体テストすることだけに集中できるようになります。

        The main goal of MO is to unit test a method in isolation of other
        domain objects. Thus, the MO approach is to fake domain objects
        by using simulated copies instead of the real objects (be careful
        MO does not implement any logic in it's fake objects, that would be
        "stubbing". All behaviours of mock objects are controlled by the unit
        test itself). This enables to
        finely unit test the method with no environment
        "noise" and to concentrate on unit testing its logic.
      </p>
      <p>
	    Servlet のテストに使用する場合、モック・オブジェクトは
		Servet コンテナをシミュレートする必要があります。言い替えると、
		Servlet API のモック実装が提供される必要があります(もちろん、
		シミュレートされる必要があるのはテストされるメソッドで使用されている
		Servlet API メソッドだけです。
		ホワイト・ペーパーで紹介されているアプローチは、
		小さなモック・オブジェクトから出発して、
		必要になったときにモック実装を追加していくというものです。
		また、コンパイル時や(JDK 1.3 の動的プロキシーを使って)実行時に
		モック実装を生成することも可能です。
        <jump anchor="mo_resources">参考文献</jump>参照)。

        When applied to servlet testing, it means mock objects need
        to be provided for simulating the servlet container. In other words
        a mock implementation of the Servlet API need to be provided (of course
        only the Servlet API methods used in the classes under test need to be
        mocked and the approach described in the white paper is to start small
        and develop the mock implementations as they are needed - Note that
        mock objects can even be generated at build time or at run time with
        JDK 1.3 dynamic proxies, see
        <jump anchor="mo_resources">resources</jump>-).
      </p>
      <p>
	    一方、Cactus の戦略は Servlet API 
		の実装を提供する本物のコンテナに依存しています。
		この文章の残りの部分では、
		各々のアプローチについて利点欠点を論じた上で結論をまとめます。

        Cactus' strategy on the other hand has been to rely on the real
        container to provide the implementation of the Servlet API.
        In the rest of this article, we'll discuss the pros and cons of each
        approach and draw a conclusion.
      </p>
      <p>
	    まずは MO をより良く理解するための例から始めましょう。

        Let's start first by an example to understand better what are MO.
      </p>

    </s1>

    <anchor id="mo_example"/>
    <s1 title="例">

      <p>
        Cactus を使った簡単なテスト・ケース :

		Simple test case using Cactus : 
      </p>

<source><![CDATA[
[...]
    MyServlet myServlet = new MyServlet();
[...]

public void beginXXX(WebRequest theRequest)
{
    theRequest.addParameter("param1", "value1");
    theRequest.addParameter("param2", "value2");
}

public void testXXX()
{
    myServlet.init(config);

    myServlet.myMethod(request, response);
    assertEquals("some value", session.getAttribute("some_name_set_in_mymethod"));
}

public void endXXX(WebResponse theResponse)
{
    String result = theResponse.getText();
    assertEquals("<html><head/><body>A GET request</body></html>", result);
}

]]></source>

      <p>
        モック・オブジェクトを使った簡単なテスト・ケース :

		Simple test case using Mock Objects : 
      </p>

<source><![CDATA[
[...]
    MockHttpServletRequest myMockHttpRequest = new MockHttpServletRequest();
    MockHttpServletResponse myMockHttpResponse = new MockHttpServletResponse();
    MockServletConfig myMockServletConfig = new MockServletConfig();
    MyServlet myServlet = new MyServlet();
[...]

public void testXXX()
{
    myMockHttpRequest.setupAddParameter("param1", "value1");
    myMockHttpRequest.setupAddParameter("param2", "value2");

    myMockHttpRequest.setExpectedAttribute("some_name_set_in_mymethod", "some value");
    myMockHttpResponse.setExpectedOutput("<html><head/><body>A GET request</body></html>");

    myServlet.init(myMockServletConfig);
    myServlet.myMethod(myMockHttpRequest, myMockHttpResponse);

    myMockHttpRequest.verify();
    myMockHttpResponse.verify();
}
]]></source>

    </s1>

    <anchor id="mo_differences"/>
    <s1 title="MO と IC の違い">

      <p>
	    MO 対 IC の利点・欠点の比較

        Comparison of pros and cons of MO versus IC.
      </p>
      <note>
	    この表は MO を使用することの利点、
		欠点についての包括的な表ではありません。
		これは(Cactus が焦点としているところの)サーバ側コードのテストにおける
		利点・欠点により焦点をあてています。


        This table is not meant to be comprehensive in
        term of benefits/inconvenients of using MO. It is more focused on
        pros and cons of MO when used for unit testing server side code (i.e.
        what Cactus is focusing on).
      </note>
      <note>
        '+' は肯定的なポイントです。
		たとえば、MO 列の '+' は MO が IC に対して有利な点を表わしています。

        A '+' indicates a positive point.For example
        a '+' in the MO column shows that it has an advantage over IC.
      </note>

      <table>
        <tr>
          <th>
            問題点
          </th>
          <th>
            MO
          </th>
          <th>
            IC
          </th>
        </tr>
        <tr>
          <td>
		    MO は周辺オブジェクトの準備ができる前(つまり、それが実装される前、
			または実装を選択する前)にメソッドをテストすることが可能です。
			したがって、たとえばコンテナを選択する前に Servlet 
			コードを書くことが可能です。
			このことは、「インフラの選択は可能な限り遅らせる」
			「単体テストを先に書く」と教える XP とうまく調和します。


            MO let us test methods even before the domain objects are ready,
            i.e. before the implementation are ready. Or before a choice of
            implementation has been made. Thus, for example, it is possible to
            write servlet code before choosing a container. This is in
            accordance with XP that says : "not commit to infrastructure choice
            before you have to" and "write unit test first".
          </td>
          <td>
            +
          </td>
          <td/>
        </tr>
        <tr>
          <td>
		    MO は包括的で、普遍的です。
			これは全ての種類の単体テストに適用できます :
			Servlet 単体テスト、JDBC 単体テスト、Struts 単体テスト、...。
			Cactus はサーバ側テストしか扱えません。
			これはつまり、もし Servlet コードの中で JDBC 接続が使用されていて、
			単体テストをデータベース・アクセスから切り離したいと考えた場合、
			さらに MO 風の戦略も必要となるということを意味します。
			こうして、あなたは 2つの戦略を学び、理解しなくてはならないのです。

            MO is comprehensive/universal. It adapts to all kind of unit
            testing :
            Servlet unit testing, JDBC unit testing, Struts unit testing, ...
            Cactus only addresses server-side testing, meaning that if in your
            Servlet code you have JDBC connections and you want to unit test
            in isolation the methods that does database access you still need
            to have a MO-like strategy, thus you need to understand and learn 2
            strategies.
          </td>
          <td>
            +
          </td>
          <td/>
        </tr>
        <tr>
          <td>
		    MO テストはコンテナ上で走らせる必要がないので、非常に高速です。
			これにより、テストを頻繁に実行することができます。
			IC テストでは、コンテナを起動し、テストを実行し、
			コンテナを終了する必要があります。
			しかしながら、これは Ant やリロード可能なコンテナ(コンテナの多くは
			動的リロードを実装しています)を使うことで緩和できます。

            Running MO tests is very fast as it does not rely on having to run
            a container. Thus tests can be run very often. IC testing needs to
            start the container, run the tests, stop the container. However,
            this can be alleviated by using Ant and by using a reloadable
            container (the majority of containers implement dynamic reloading).
          </td>
          <td>
            +
          </td>
          <td/>
        </tr>
        <tr>
          <td>
		    MO を使うことで、
			開発者はコードのリファクタリングを強要されます。
			例えば、周辺オブジェクトのモック実装を開発するためには、
			そのインターフェースが提供されていなくてはなりません。
			他にも、多くの細かいデータを渡す代わりに、賢いハンドラを渡す
			(こうしてより良いカプセル化がもたらされます)
			といったような、もっと微妙なリファクタリングも行なわれます。
			これは XP のリファクタリング規則に従っています。もし、
			あなたが既に存在するコードのテストを書かなくてはいけないとしたら、
			それは容易に悪夢と化すであろうことを覚えておいてください...。

            Using MO force the developer to refactor his code. As an example he
            needs to ensure that interfaces are provided for domain objects so
            that a Mock implementation can be implemented. There are other
            more subtle refactoring involved like smart handler passing instead
            of more fine grained data (thus leading to better encapsulation). It
            follows XP refactoring rules. Note that if you need to implement
            tests for existing code it can easily become a nightmare ...
          </td>
          <td>
            +
          </td>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    MO を使っても、
			そのクラスが選択されたコンテナで正しく動作するかどうかは判りません。
			一方、
			IC テストは全てのコードがコンテナ内で完璧にうまく動作することを保証します。

            Using MO, it is not sure the classes will run correctly in the
            chosen container. On the other hand, IC tests ensures that
            all code will run perfectly well in container.
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    MO テストは粒度が非常に細かくなる傾向があります。そのことで、
			オブジェクト間の連携が正しく動作することの保証がなくなり、
			もっと粒度の粗いテスト(統合テストや機能テスト)が必要になります。

            MO tests tend to be very fine-grained. Thus, there is no assurance
            that object interactions will work properly and thus more coarse
            grained tests tests are a must (integration tests, functional
            tests).
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    汎用の MO ライブラリを使うと、
			いくつかの MO プラクティスに反することになります。
			たとえば、周辺オブジェクトのアサーションをテスト・ケースではなく、
			モック実装に含めて集約すること
			(これはリファクタリングされたアサーションと呼ばれます)
			は良い習慣であるとされています。
			これはモック実装がプロジェクトに特化したものでなくては不可能です。
			ですので、
			MO は汎用ライブラリという考え方には馴染まないところがあるのかもしれません。
			おそらくは中庸となる点が見つかることでしょう。

            Using generic MO libraries is against some of MO practices. For
            example, a good practice is to factorize domain object asserts in
            the mock implementation instead of in the test case (this is called
            Refactored Assertions). This is
            possible only if the Mock implementation is project specific. So,
            for some parts, MO does not fit that well with the idea of generic
            libraries. A middle ground could probably be found.
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    MO を使うということは、単純なことではありません。それは
		    いくらかの訓練と経験を必要とします。
			JUnit を使った単体テストと同様に、従うべき方法論が存在しま
		    す。そのいくつかは :


            Using MO is not simple. It needs some discipline and some
            experience. Same as for unit tesing using JUnit, there are some
            methodologies to follow. Some are :
            <ul>
              <li>
			    無数の MO を実装するハメになって押し潰されないように、
				MO の実装は可能な限り単純である必要があります。
				言い替えれば、最初は何もしないメソッドを、
				そしてゆっくり時間をかけて、リファクタリングを通して、
			    そのときに必要なものだけを実装しなさい。

                In order not to be weighted down by having to implement myriad
                of MO, these implementation need to be the simplest possible,
                i.e. do nothing method at first and then slowly over time,
                during refactoring, implement what is needed at the current
                time.
              </li>
              <li>
			    MO の中で周辺オブジェクトのロジックを再実装する誘惑に負けてはいけません。
				全ての MO は、
				ほとんどロジックが含まれていないようにしなくてはいけません。
				
                One must resist the temptation to reimplement the domain logic
                in the MO. There must be almost no logic at all in MO.
              </li>
              <li>
			    MO から他の MO を呼び出してはいけません...
				そうしなくてはいけないのであれば、
				その MO はリファクタリングを必要としています！

                MO must not make calls to other MOs ... When it happens, there
                is a need for MO refactoring !
              </li>
            </ul>
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    いくつかのケースでは、
			MO は通常であれば必要とされない生成 API を必要とします。
			たとえば、Servlet
			内部で使用される周辺オブジェクトのモック版を初期化するために 
			Servlet の中で <code>init(MockObject)</code> 
			を呼び出す必要があったりします。
			また、コードはビジネス要件のためではなく、
			テストのために(より柔軟性を持つとしても)より複雑になります :
			たとえば、通常は必要のないファクトリが、
			MO オブジェクトを取得するためだけに必要となるかもしれません。

            In some cases MO mandates creating API that are no normally
            needed, like having to offer a
            <code>init(MockObject)</code> method in a Servlet in order to
            initialize a mock version of an internally used domain object. Also
            the code may become more complex (even if more flexible) because
            of the need for testing and not because of business requirements :
            for example, one might need to introduce a factory when it was not
            needed simply to be able to provide MO objects from the factory.
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    全ての要件を満たす汎用 MO ライブラリを作ることは不可能でしょう。
			たとえば、汎用 JDBC MO ライブラリは作れないでしょうし、
			おそらくはデータベース MO ライブラリを必要とするでしょう。
			また、汎用 MO ライブラリのコストと複雑性は、
			必要なシミュレート部分だけを一から再実装するのと比べても、
			高くつくものになるでしょう。


            It may not be possible to create generic MO libraries that fit all
            the needs. For example a generic JDBC MO library may not be possible
            and might need database specific MO libraries. Also the cost and
            complexity of a generic MO library may be higher than just
            reimplementing from scratch just the needed mocked parts.
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
        <tr>
          <td>
		    MO はいつもうまくいくとは限りません。たとえば、シミュレー
            トされた API は正しいインターフェースを持たなくてはいけませんし、
			内部オブジェクトをオーバーライド/セットしなくてはいけません。

            MO does not always work well. For example the API being mocked need
            to offer the correct interfaces and means to override/set internal
            objects.
          </td>
          <td/>
          <td>
            +
          </td>
        </tr>
      </table>

    </s1>

    <anchor id="mo_conclusion"/>
    <s1 title="結論">

      <p>
	    モック・オブジェクトは通常の Java クラスの単体テストと、
		コンテナ・コンポーネントのサーバ側テストのギャップを埋める可能性のある、
		非常に興味深い単体テスト手法です。
		Cactus の現在のテスト方法と、モック・オブジェクトの最も大きな違いは、
		Cactus テストはより粒度の粗いテストを目指していて、
		開発コードがコンテナの中で動作することを保証するということです。
		一方、モック・オブジェクトは Servlet の単体テストに限らず、
		コードのあらゆる領域をカバーしているため、より包括的です。

        Mock Objects are a very interesting way of doing unit testing which
        could bridge the gap between standard java class unit testing and
        server-side testing of container components. The biggest
        difference between the way Cactus currently works and Mock Objects is
        that Cactus tests tend to be more coarse-grained and they also ensure
        that developed code will run in the container. On the other hand, Mock
        Objects are more satisfactory intellectually because they are not
        limited to servlet unit testing but cover the whole spectrum of code.
      </p>
      <p>
	    私達は Cactus テストの粒度は丁度良いレベルだと信じています。
		粒度の細かいテストをすることは素晴らしいことですが、
		しかしそれには多くの労力を必要とします。
		Cactus テストは中庸にあるようで、単体テストを十分に行いつつ、
		同時にデプロイ後にもコードが正しく動くという*十分な*自信を与えます。

        We believe the graininess of Cactus tests is just correct. Having
        fine-grained tests is nice but it is also a lot of effort. It seems
        Cactus
        tests are a middle ground where you can still do unit tests fine
        enough and at the same time it gives you *enough* confidence that your
        tests will run fine when deployed.
      </p>
      <p>
	    また、<link href="goals.html">目標</link>でも述べた通り、
		将来、より多くのコンポーネントが使われるようになれば、
		Cactus のようなフレームワークはますます有益なものになると、
		私達は考えています。Cactus は、
		コードがコンテナの中で正しく動作するのだという自信を与えてくれます。

        Also, as described on the <link href="goals.html">Cactus' goals
        page</link>, we think that a framework like Cactus will be more and
        more useful as we use more and more components in the future because
        it will provide
        the needed confidence that the code will run ok in the container.
      </p>
      <p>
	    私達はまた、正しい MO テストを書くことは難しく、
		いくらかの訓練を必要とするものであると考えています。
		MO は、より良いコードを書かせてくれるという点では素晴しいですが、
		Cactus テストに比べて難解です。

        We also believe that writing correctly MO tests is a difficult process
        that need some training. MO are good because they let you write better
        code but it is more difficult to understand than Cactus tests.
      </p>
      <p>
	    最後に、
		私達は MO と Cactus は以下の 2領域で相互補完的であると信じます。

        Finally, we believe that MO and Cactus are complementary in 2 areas :
        <ul>
          <li>
		    開発フェーズにおいて、
			MO はコードのロジックだけを単体テストするのに使用できます。
			テストは実行が早く、容易に IDE の中から使用することができます。
			数時間に一度、
			オブジェクト間の連携とコンテナとの連携をテストするための 
			Cactus テストを実行します。
			そして、実際のプラットフォームにデプロイした後、
			機能テスト/受け入れテストを実施します。
			これは、あなたがフル・サイクルのテストを
			実施したい場合の話だということに注意してください。
			ショート・サイクルのテストでは、
			Cactus テストと機能テスト/受け入れテストだけで良いでしょう。
			
            During the development phase, MO could be used to unit test the
            code logic only. They run fast and you could use them easily
            inside your IDE. Then every few hours, you'll run the Cactus tests
            which test interactions between objects and container interactions.
            Then you'll run the functional/acceptance tests when you deploy
            to the real platform. Note that this is if you want to do the full
            cycle. A short cycle could simply be Cactus tests and functional
            /acceptance tests.
          </li>
          <li>
		    Cactus はサーバ側コードに焦点をあてたものです。
			しかし、MO (あるはスタブ)は Cactus テストの中で例えば JDBC 接続や 
			LDAP 接続などをシミュレートするのに使用することができます。
			そこに制限は存在しません。

            Cactus focuses on server side code. However you can use MO (or
            stubs) within Cactus tests for simulating a JDBC connection, an
            LDAP connection, ... for example. There are no restrictions.
          </li>
        </ul>
      </p>
      <p>
	    私達は MO vs IC について、
		ぜひフィードバックをいただきたいと思っています。
		何かご意見がありましたら、
        <link href="mailinglist.html">Cactus メーリング・リスト</link>
		までお送りください。

        We would very much like to have your feedback on MO vs IC. Please post
        your feedback on the
        <link href="mailinglist.html">Cactus mailing list</link>.
      </p>
      <p>
	    どうもありがとう。

        Thanks a lot.
      </p>

    </s1>

    <anchor id="mo_resources"/>
    <s1 title="MO に関する参考文献">

      <p>
        リンク :

		Some links :
      </p>
      <p>
        <ul>
          <li>
            <link href="http://mockobjects.sourceforge.net/endotesting.html">
            "Endo-Testing : Unit Testing with Mock Objects"</link> (PDF).
            MO の背後にあるビジョンについて説明しています。

            <link href="http://mockobjects.sourceforge.net/endotesting.html">
            "Endo-Testing : Unit Testing with Mock Objects"</link> (PDF).
            Describes the vision behind MO.
          </li>
          <li>
            <link href="http://c2.com/ppr/wiki/RecentChanges/MockObject.html">
            Wiki によるモック・オブジェクト討議</link>。

            <link href="http://c2.com/ppr/wiki/RecentChanges/MockObject.html">
            Mock Object discussions on Wiki</link>.
          </li>
          <li>
            SourceForge 上の
			<link href="http://mockobjects.sourceforge.net">
			Mock Object プロジェクト</link>。
			MO フレームワークと、いくつかのモックの実装。

            <link href="http://mockobjects.sourceforge.net">Mock Object
            project</link> on SourceForge. MO framework and some mock
            implementations.
          </li>
          <li>
            <link
            href="http://www.xpdeveloper.com/cgi-bin/wiki.cgi?MockMaker">Mock
            Maker</link>。SourceForge モック・オブジェクト用に、
			コンパイル時 MO 実装を生成する。
			生成はインターフェースから行なわれる。

            <link
            href="http://www.xpdeveloper.com/cgi-bin/wiki.cgi?MockMaker">Mock
            Maker</link>. Generates build time MO implementations for the
            SourceForge Mock Objects project. Generation is done from
            interfaces.
          </li>
          <li>
            <link href="http://tammofreese.de/easymock/">Easy
            Mock</link>。
            動的プロキシー(JDK 1.3)を使用して実行時モック実装が提供される。
			このため、モック実装を記述したり、生成したりしなくてもよくなる。

            <link href="http://tammofreese.de/easymock/">Easy Mock</link>.
            Uses dynamic proxies (JDK 1.3) to provide runtime
            mock implementations, thus eliminating the need for generating/
            writing the mock implementations.
          </li>
          <li>
            <link href="http://www.xpdeveloper.com">xpdeveloper.com</link>
			ウェブ・サイトと Extreme Tuesday Club (Xtc) ...

            <link href="http://www.xpdeveloper.com">xpdeveloper.com</link> web
            site and it's Extreme Tuesday Club (Xtc) ...
          </li>
        </ul>
      </p>

    </s1>

  </body>
</document>
