JMockitを使ってStaticクラスをMock

10年近く前、まだテストなんて概念すら知らないときに作ったシステムがいまだに動いています。
当時はPHPしか経験がなかったのですが、開発はJavaでなければいけないということでHello Worldから始めました。
なんとか完成したものの、変更に次ぐ変更によって何もかもが相互に依存しまくり、もはや意味がわからない状態になっています。

本当ならすべてを書き直したいくらいですが、時間もないのでぐちゃぐちゃのままメンテナンスしなければいけない。。

そこで、なんとかできるところだけでもテストを書きたいとネットを徘徊していたところ、JMockitを見つけたので試してみました。

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

いろいろ間違ってるかもしれませんがとりあえず晒します。


gist9015683

reference:
http://d.hatena.ne.jp/ryoasai/20110107/1294427245
http://jmockit.googlecode.com/svn/trunk/www/tutorial/AnExample.html

SQLのWHERE条件

ANDで繋がってるWHEREの条件は左から右に順番に見ていくので、とてつもなく大きなデータを抽出する場合はより結果の絞れる条件を左に持ってくると良い。ということだと思う。
実際やってみたけど、自分の条件ではあまり変わらなかった。。

Queries with all operations on the WHERE clause connected by ANDs are processed from the left to right. So, if a operation returns false, all other operations in the right side of it are ignored, because they can’t change the AND result anyway. It is better then to start your WHERE clause with the operations that returns false most of the time.

https://medium.com/tech-talk/f834f09bafaf

JPAについて調べてみた

ほぼ毎日使うのだけれど、かなり曖昧な理解のまま放置していた。
エラーが起こるたびに場当たり的な対処をしてきましたが、これではいけないと1から調べてみました。
間違っている箇所もあるかもしれませんので、お気づきの点はぜひご指摘ください。

永続化コンテキスト、EntityManager
JPAには「永続化コンテキスト」と呼ばれる入れ物が用意されている。永続化コンテキストとHibernateのセッションは同じことらしい。
この入れ物にはエンティティと呼ばれるDBの1行1行に対応するモデルが入っている。例えばDBに「性=山田、名=太郎、年齢=40歳」みたいな1行のレコードがあるとすると、それに対応するエンティティにはプロパティが3つあってlastNameに山田, firstNameに太郎, ageに40が入っているような形。EntityManagerはこの永続化コンテキストという入れ物や各エンティティを管理するもの。

エンティティをsaveしたり、既存のデータをDBから持ってくると、レコードの内容がエンティティとして永続化コンテキストの中に放り込まれる。このときに永続化コンテキスト内で管理されているエンティティはmanagedという状態になる。永続化コンテキストの中に入れたエンティティを、アプリケーション側で変更してからsaveを実行してもDBには反映されない。saveはアプリケーションで行ったエンティティの変更を永続化コンテキストに反映させているだけなので、永続化コンテキストからDBに書き込みを行うには別途flush(commit)する必要がある。ただこの辺りはアプリケーションや使ってるフレームワークがどう処理するかによって異なる。

管理されていたエンティティが永続化コンテキストから切り離されるとエンティティはdetached状態になる。
detached状態のエンティティはDBから取得したり、エンティティの変更を反映させたりといった処理ができなくなる。開発している時、PlayのインメモリDBを使っていると時々出てくる「detached entity passed to persist」というエラーは、操作しようとしたエンティティが何らかの理由で永続化コンテキストから切り離されているため、操作ができないという意味になる。

エンティティに対して行う処理:
EntityManagerがエンティティに対して行う処理にはpersist, remove, merge, refreshがある。persist, removeは永続化コンテキストに対する処理なので、上で触れたように実行しても実際にアプリケーションで行ったエンティティへの変更がデータベースに反映されるのはflush(commit)処理の後になる。

persist: 新しいオブジェクトを永続化コンテキストに追加する
remove: 永続化コンテキストにあるエンティティを削除する
merge: detached状態のエンティティをmanaged状態にする
refresh: エンティティの内容をデータベースと同期する。変更内容はデータベースのもので上書きされる

clearはすべてのエンティティをdetached状態にする。
closeは永続化コンテキストを破棄してEntityManagerを終了する。

ref: http://openjpa.apache.org/builds/latest/docs/docbook/manual.html#jpa_overview_em_lifecycle

トランザクション
トランザクションは追加、更新、削除といったDB処理をまとめた作業の単位。トランザクションに対する命令にはbegin, commit, rollbackがある。トランザクションを開始するにはbeginを呼び出す。実施するにはcommitを呼び出す。beginからcommitまでの間に行うDB処理を記述する。トランザクション中に処理が失敗した場合はrollbackによりトランザクションで行おうとしていたDBへの処理をすべて取り消すことができる。
ref1: http://openjpa.apache.org/builds/latest/docs/docbook/manual.html#jpa_overview_emfactory_perscontext_trans
ref2: http://www.techscore.com/tech/sql/SQL11/11_01.html/

リレーション:
エンティティと関連付けられたエンティティ(OneToManyとか)に対する処理を自動で行う場合はCascadeTypeを指定する。
CascadeType.PERSIST: 新規に永続化コンテキストにエンティティを追加する場合、このフィールドのエンティティも追加する。PERSISTの指定がなく、永続化コンテキストに追加されていないエンティティが関連付けられているとエラーが出る
CascadeType.REMOVE: 親が削除されると指定したフィールドのエンティティも削除される
CascadeType.REFRESH: 親がrefresh()されるとこのフィールドのエンティティもrefresh()される
CascadeType.MERGE: 親がmerge()されるとこのフィールドのエンティティもmerge()される
ref: http://openjpa.apache.org/builds/latest/docs/docbook/manual.html#jpa_overview_meta_cascade

関連付けされたフィールドをどのように呼び出すかをEagerかLazyで指定できる。
Eager Lodingはフィールドの呼び出しを最初の呼び出しで行う。
Lazy Loadingはそのフィールドにアクセスがあった時点でフィールドをデータベースから呼び出す。
顧客テーブルと電話番号テーブルが1対多で関連付けされていて「山田さん」には「携帯」「自宅」「実家」という複数の電話番号がひも付けされているとする。Eager Loadingを指定すると、親になる「山田さん」エンティティを呼び出したときに、一緒に電話番号たちも持ってくる。Lazy Loadingだと「山田さん」エンティティだけを先に呼び出しておいて、電話番号はアプリケーション側で呼ばれてから(iteratorへのアクセス等、利用されるときに)取ってくる。
ref: http://openjpa.apache.org/builds/latest/docs/docbook/manual.html#jpa_overview_meta_fetch

Apple Mac miniで作るVMware vSphereラボ環境 ー vCenter Serverのインストール

DCと仮想ESXiを追加したのでvCenter Serverをセットアップします。
まずWindows 2008 R2をインストールするのですが、評価版のイメージがかなり古いようです。

ダウンロード時のままだとvCenter Serverどころか、SQL Server 2008 R2 Express、VMware Toolsもインストールできません。
vSphereのインストールの前にWindows Updateを実行してWindowsを最新の状態にしてください。
評価版でもUpdateは可能でした。

Windows Updateが終了したら"VMware vCenter Simple Install"をクリックするだけです。
VCP対策としては、ここでvCenter管理のドキュメントを見ながらSQLの評価版を使ってセットアップを試すのも良さそうです。
今度、vCenterアプライアンスのデプロイも試してみようと思います。


Windowsのイメージが古いことに気付かず、少しハマったのでエラーメッセージをメモしておきます。

セットアップ画面からWindows Installer 4.5をインストールしようとすると下記のようなエラーがでます。
「この更新プログラムはお使いのコンピュータには適用できません 」

それからこの状態でVMware Toolsをインストールしようとするとこのエラーがでます。
VMware Toolsは、仮想マシン内にのみインストールしてください」

Apple Mac miniで作るVMware vSphereラボ環境 ー Nested ESXiとDCのインストール

前回までの内容でMac miniにESXiがインストールできました。
これから仮想ESXi、vCenter Server、FreeNASを使った仮想ストレージを用意します。
セットアップするのは次の5つの仮想マシンです。

  1. ドメインコントローラ(DC)
  2. ESXi x 2台
  3. vCenter Server
  4. iSCSIストレージ(FreeNAS)

続く説明では、前回までにセットアップしたMac mini上にインストールしたESXiは「物理ESXi」と呼びます。
その物理ESXiの中にインストールするESXiについては、仮想ESXi(Nested ESXi)と呼ぶ事にします。

まずは仮想ESXi、DCを配置する物理ESXiの仮想スイッチを作成します。
この環境では自宅LANに接続された仮想スイッチを「Home Network」とし、仮想ESXiやDCが所属するラボ内のネットワークを「Lab Network」としました。もう一つは「iSCSI Network」というSAN用の仮想スイッチを作成してFreeNASと各仮想ESXiを追加します。
※Lab NetworkとiSCSI Networkでは仮想スイッチの「無差別モード」を「承諾」に設定します。

仮想マシン、VMKernelのネットワークは下記のようにしました。

  • Home Network - 192.168.3.x/24
  • VM Network - 192.168.30.x/24
  • iSCSI Network - 192.168.33.x/24


次にドメインコントローラをセットアップします。
こちらのブログにスクリーンショット付きで詳しく説明がありましたので、こちらを参考にしてください。
Windows 2008 R2にActive Directoryドメインコントローラをセットアップする
CPU、メモリはAD、DNSがかろうじて動作する必要最小限でいいと思います。

次に仮想ESXiをインストールします。
仮想ESXiはインストール時に設定ファイル(vmx)を書き換える必要がありますので、物理ESXiのSSHを有効にしておいてください。
まず仮想マシンを作成します。OSは後ほど変更しますので、ここでは「その他(64bit)」等、適当なものを選択してください。
CPUは2ソケットの1コアで、メモリは4GBとします。

64bitのOSを仮想ESXi上で稼働させる場合は「オプション」タブから「CPU/MMUの仮想化」を選択して「Intel(R) VT-x/AMD-Vを命令セット仮想化に使用し、Intel EPT/AMD RVIをMMU仮想化に使用」を選択します。次に物理ESXiにSSHで接続して、仮想ESXiの設定ファイル(.vmx)に「vhv.enable = "TRUE"」の一行を追加します。
それから仮想ハードウェアのバージョンも9にしておく必要があります。

juzow:~ juzow$ ssh -l root 192.168.3.8
Password: 
The time and date of this login have been sent to the system logs.

VMware offers supported, powerful system administration tools.  Please
see www.vmware.com/go/sysadmintools for details.

The ESXi Shell can be disabled by an administrative user. See the
vSphere Security documentation for more information.
~ # vi /vmfs/volumes/datastore1/esxi01/esxi01.vmx
#...
#... configs ...
#...
vhv.enable = "TRUE"

あとは物理ESXiの時と同じようにESXiをインストールするだけです。
テスト環境なのでSSHやESXi Shellは最初から有効にしておいてもいいかと思います。

次はvCenter ServerとFreeNASをセットアップします。

Source:
Windows 2008 R2にActive Directoryドメインコントローラをセットアップする
VirtualGhetto:How to enable nested ESXi and Other hypervisors in vSphere 5.1
VMware Community - Running Nested VMs