クリエイター:メタボ兔

ウェブやアプリの開発者で利用する色な技術やサーバーや開発環境の設定について共有する場

EasyMockでcmp、capture

概要

EasyMockを利用してテストケースを作成する際に以下の内容で対応方法を調べていました。

  • mainのソースのクラスのequalsをオーバーライドする等、テストの為に修正はしたくない
  • メソッド内部の変数をテスト内容に入れないので、expectで確認するメソッドのパラメターを判定したい

例のソース

Map<String, String> expectMap = new HashMap<String, String>();
...
sampleClass.test(eq(stringA), eq(intB), eq(mapC), eq(booleanD));

確認したい内容

  • mapCのキー&値が一致
  • mapCの特定のキーについては除外

eqのような判定をカスタマイズ

eqと比較内容をカスタマイズすれば「確認したい内容」のみ定義できるかと思いました調べたところ以下のような内容がありました。

stackoverflow.com

こんな感じで作ってみました。expectMapにあるキーを基準で比較するのを想定しました。

   // 比較内容を定義
    private class MapComparator implements Comparator<Map<String, String>> {
        @Override
        public int compare(Map<String, String> expected, Map<String, String> actual) {
            for (String key : expected.keySet()) {
                if (!actual.containsKey(key)) return -1;
                if (!StringUtils.equals(expected.get(key), actual.get(key))) return 1;
            }
            return 0;
        }       
    }
    
...

    // 使用例
    Map<String, String> expectMap = new HashMap<String, String>();
    expectMap.put("key1", "value1");
    expectMap.put("key2", "value2");

    MapComparator mapComparator = new MapComparator();
    
    sampleClass.test(eq(stringA), eq(intB), EasyMock.cmp(expectMap, mapComparator, LogicalOperator.EQUAL), eq(booleanD));
    EasyMock.expectLastCall();
...

結果

結果としてダメでした。MapComparator#compareがテストメソッドのパラメーター分繰り返して呼ばれて、actualにtestメソッドの第一パラメーターから第四パラメーターが順番で入ってくることになります。

それでcast exceptionが発生されます。これを使えるのはパラメーターが一つの場合のみかと思います。

capture

cmpでパラメーターが複数の時の対応が出来ないことで調査を続けるとEasyMock.captureというものがありました。テストメソッドが呼ばれる時の値を指定した変数に格納(?)してくれるので後で値を比較が可能になります。

www.programcreek.com

...
    // sampleClass.testが実行する時、第3番目のパラメターがcaptureFeatureSetTagへ格納される。
    Capture<Map<String, String>> actualCapture = new Capture<Map<String,String>>();
    sampleClass.test(eq(stringA), eq(intB), EasyMock.capture(actualCapture), eq(booleanD));
    EasyMock.expectLastCall();

    // テスト対象のメソッドを実行
    replayAll();
    testClass.excute(parameter);
    verifyAll();
        
    // 使用例
    Map<String, String> expectMap = new HashMap<String, String>();
    expectMap.put("key1", "value1");
    expectMap.put("key2", "value2");

    // captureFeatureSetTagと比較("key3"を除外)
    Map<String, String> actualMap = actualCapture.getValue();
    actualMap.remove("key3");
    assertEquals(expectMap, actualMap);
...

結論

今回の対応ではEasyMock.captureを利用して対応ができましたが、個人的にはcmpもやってみたいなと思いました。

VMWareへWindows 11をインストール

概要

開発でテスト用で利用する目的でWindows 11が必要になってVMWareへインストールした手順や問題を整理してみました。

ISOをダウンロード

ダウンロード先の一番したにある「Windows 11 ディスク イメージ (ISO) をダウンロードする」からダウンロードします。

www.microsoft.com

f:id:FattyRabbit:20211221114428p:plain

VMWareの設定

  • HDD:80G
  • Memory:4G

設定によりと思いますが、CMOSでCDからBootされるようにしている必要があります。VMを起動して直ぐEscキーを押したら入りました。

インストール

問題発生

普通にインストール手順で設定してインストールOSの種類を選択した後に以下の「このPCは、このバージョンのWindowsをインストールするために最小システム要件を満たしません。詳細については、https://aka.ms/WindowsSysReqを参照してください。」とメッセージが出てインストールが出来ない状態になりました。

f:id:FattyRabbit:20211221115613p:plain

ここで何を選択しても以下のメッセージが出ます。

f:id:FattyRabbit:20211221115642p:plain

問題解決

メッセージが出たら「Shift + F10」でコマンドプロンプトを立ち上げて「regedit」と入力してエンターを押すとレジストリエディターが立ち上がります。

f:id:FattyRabbit:20211221120028p:plain

レジストリエディターが立ち上がったら、「HKEY_LOCAL_MACHINE\SYSTEM\Setup」の下に「LabConfig」というキーを追加します。そのキーの中にDWORDで「BypassTPMCheck」と「BypassSecureBootCheck」を作成します。

f:id:FattyRabbit:20211221120052p:plain

両方の値もダブルクリックで「1」を設定しておきます。ここでのレジストリインストーラ用の一時的なもので、再起動などで消えるので間違えたりしても影響はありません。

再起動はせずに追加できたらすべて画面を閉じてインストールを進めていきます。

完了

インストールできました。

f:id:FattyRabbit:20211221120349p:plain

Vagrantにmailhogの構築

概要

開発環境(Vagrant + ubuntu/trusty64)にメールの確認用でMailhogをインストールした話をまとめてみました。

Go言語のインストール

MailhogをインストールするためにGo言語をインストールします。

失敗

GUEST> sudo apt-get install golang-go

この方法でインストールするとOSのバージョンが低いせいかgoが1.2.1がインストールされてしまいます。このバージョンだとMailhogをインストールする際に以下のエラーが発生します。

package github.com/mailhog/MailHog
    imports github.com/gorilla/pat
    imports github.com/gorilla/context
    imports github.com/gorilla/mux
    imports context: unrecognized import path "context"
package github.com/mailhog/MailHog
    imports github.com/gorilla/pat
    imports github.com/gorilla/context
    imports github.com/gorilla/mux
    imports github.com/ian-kent/envconf
    imports github.com/ian-kent/go-log/log
    imports github.com/t-k/fluent-logger-golang/fluent
    imports github.com/tinylib/msgp/msgp
    imports github.com/philhofer/fwd
    imports github.com/mailhog/MailHog-Server/api
    imports github.com/gorilla/websocket
    imports net/http/httptrace: unrecognized import path "net/http/httptrace"

成功した物

使用する基本ツールをインストールします。

GUEST> sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install git

GO言語をダウンロードします。

GUEST> curl -O https://storage.googleapis.com/golang/go1.9.1.linux-amd64.tar.gz

圧縮ファイルを解凍して/usr/localへ移動します。

GUEST> tar -xvf go1.9.1.linux-amd64.tar.gz
GUEST> sudo mv go /usr/local
GUEST> rm  go1.9.1.linux-amd64.tar.gz

環境設定を行います。

GUEST> touch /home/vagrant/.bash_profile
GUEST> echo "export PATH=$PATH:/usr/local/go/bin" >> /home/vagrant/.bash_profile
GUEST> echo `export GOPATH=/home/vagrant/workspace:$PATH` >> /home/vagrant/.bash_profile
GUEST> export GOPATH=/home/vagrant/workspace
GUEST> mkdir -p "$GOPATH/bin" 

Mailhogをインストール

Mailhogとmhsendmailをインストールします。

GUEST> go get github.com/mailhog/MailHog
GUEST> go get github.com/mailhog/mhsendmail
GUEST> sudo cp /home/juampy/gocode/bin/MailHog /usr/local/bin/mailhog
GUEST> sudo cp /home/juampy/gocode/bin/mhsendmail /usr/local/bin/mhsendmail

サービス登録ファイルを作成します。

GUEST> sudo vi /etc/init/mailhog.conf
description "mailhog-service"

start on started networking
stop on runlevel [!2345]

exec /usr/local/bin/mailhog -api-bind-addr 192.168.33.10:8025 -ui-bind-addr 192.168.33.10:8025 -smtp-bind-addr 127.0.0.1:1025

*「192.168.33.10」はホストからGUESTへ接続可能なIPです。127.0.0.1で設定するとHOSTから接続できないことを注意してください。

サーバーが起動時に実行するように設定します。

GUEST> sudo sysv-rc-conf mailhog on
GUEST> sudo sysv-rc-conf -list | grep mailhog

起動します。

GUEST> sudo service mailhog start

確認

http://192.168.33.10:8025」で接続してみます。

f:id:FattyRabbit:20210802233607p:plain

Vagrantの時刻のズレ

概要

Vagrantで開発環境を構成して起動時間が長くなるとPCのスリープなったりしたのが原因なのか時刻がずれたりしましたので、その対応方法を調べてみました。

ホスト川に時刻を同期させる方法

色々試しましたが、一番良い方法だと思います。Vagrantfileに以下の内容を追記し再起動します。

config.vm.provider :virtualbox do |vb|
  vb.customize ["setextradata", :id, "VBoxInternal/Devices/VMMDev/0/Config/GetHostTimeDisabled", 0]
end

その他

Dockerの環境はどうなったか。。。

Javaの呼び出し元を取得(Stacktrace)

概要

実装の時エラーのスタックトレース(Stack Trace)のように呼び出し元(階層)を表示したいとか表示したい場合がありますよね(実は自分もあまりないと思う)?その時やり方を紹介したいと思います。

ソースで説明

面倒なのでいきなりソース&コメントで何とかやります。

    /**
    * 呼び出し元のスタックを取得
    * 
    * @return Stacktraceの文字列
    */
    private String getCalleStack() {
        // RuntimeExceptionを利用してスタックトレースを取得
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        new RuntimeException().printStackTrace(pw);
        pw.flush();
        String stacktrace = sw.toString();
        
        // スタックトレースを文字列として取得し、改行で分割し、空行、"at"のみの行を捨てる
        List<String> lines = Arrays.stream(stacktrace.split("[ \t\n]"))
                .map(s -> s.trim())
                .filter(s -> s.length() > 0 && !s.equals("at") && !s.contains("java.lang.Thread"))
                .collect(Collectors.toList());

        // 例外名称を捨てる
        lines.remove(0);

        // それらを改行コードで接続する。
        return lines.stream().collect(Collectors.joining("\n"));
    }

取得したくないクラス名や内容があったら「filter」の条件を増やせば良いかと思いました。