JUnit で標準出力結果を検証

System.setOut で標準出力先を切り替えたのを元に戻す - Oboe吹きプログラマの黙示録

より、切り替えによるJUnit で標準出力結果を検証する

テストケースを以下のように書けば良い。
例) "OK"だけを標準出力するメソッドをテスト
System.lineSeparator() を付与して比較検証するようにする必要がある

@Test
public void test() {
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    System.setOut(new PrintStream(bo));

    //テスト対象メソッド呼び出し

    String resout = bo.toString();
    MatcherAssert.assertThat(resout, CoreMatchers.is("OK" + System.lineSeparator()));

    // 元に戻して、コンソールにも出す
    System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
    System.out.println(resout);
}

System.setOut で標準出力先を切り替えたのを元に戻す

標準出力のバンドル FileDescriptor.out で戻せば良い。

System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));

例)ファイルに書いていて、元に戻す。

try(FileOutputStream fo = new FileOutputStream(new File("/work/test.txt"))){
   
   System.setOut(new PrintStream(fo));

   // 標準出力は、File("/work/test.txt") に出力される。

}catch(IOException e){
    e.printStackTrace();
}

// 元に戻す
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));

try-with-resources を書かずに、ByteArrayOutputStream に書き出す。

ByteArrayOutputStream bo = new ByteArrayOutputStream();
System.setOut(new PrintStream(bo));

System.out.println("この出力は、ByteArrayOutputStream");

System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
try{ bo.close(); }catch(IOException e){}

System.out.println("after");
System.out.println(bo.toString());

実行結果は、、

after
この出力は、ByteArrayOutputStream

リストの比較

JUnit リストの比較
Eclipse で、JUnit を書いていると、コード補完でうまく出てこなくて
いつもイライラするので、メモ

import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
MatcherAssert.assertThat(list1, CoreMatchers.is(list2));
MatcherAssert.assertThat(list1, CoreMatchers.hasItem("b"));
MatcherAssert.assertThat(null, CoreMatchers.nullValue());
MatcherAssert.assertThat(list1, CoreMatchers.is(list2));

mybatis の foreach は、ネスト(入れ子)を書けるか?

Yes. 書けます。

mybatis foreach で、1つの foreach で良く使うのは、バルクインサートを書く時、、

INSERT INTO items  ( id, name. length
) VALUES 
<foreach collection="list" item="e" separator=",">
    ( #{e.id}, #{e.name}, #{e.length} )
</foreach>

バルクインサートでなお且つ、インサート文で指定するカラムも可変だった場合、
これは、foreach の中で、もう一度 foraech にする必要がある。

<insert id="insert" parameterType="map">
INSERT INTO ${scheme}.${tablename}
   <foreach collection="columns" item="cname" open="(" close=")" separator=",">
     ${cname}
   </foreach>
VALUES
   <foreach collection="values" item="vlist" separator=",">
      <foreach collection="vlist" item="v" open="(" close=")" separator=",">
        #{v}
      </foreach>
   </foreach>
</insert>

map に渡す values は、List<List<Object>> という形でデータを渡すことになる。

Stream から 配列生成

Stream<T> の toArray(T::new);

toArray の引数が IntFunction<A> なのであるからといって、

.toArray(v->new T[v]);

と書く人は少ない。

IntStream toArray() が、int[] を生成するのだが、

int[] intary = IntStream.rangeClosed(1, 5).toArray();

Integer の配列は、IntStream のまま、toArray で作成できるわけがなく、
一旦、IntStream から、Stream<Integer> にしないと、toArray で変換できない。

例)

Integer[] integerAry = IntStream.rangeClosed(1, 5).mapToObj(Integer::valueOf).toArray(Integer[]::new);

mapToObj じゃなくて、IntStream なんだから、boxed

Stream<Integer> integerStream = IntStream.rangeClosed(1, 5).boxed();
Integer[] integerAry = integerStream.toArray(Integer[]::new);

つまり、

Integer[] integerAry = IntStream.rangeClosed(1, 5).boxed().toArray(Integer[]::new);

Stream ではなく、省略可能引数のメソッドの呼び出しも、配列に変換するメソッドにすることになる視点も
面白い。

public  T[]  setandgetFunction(T...t) {
     // TODO
     return t;
}

JUnit static import

JUnit の時ぐらいしか使わない static import

org.junit.Assert を使ってるのか、org.hamcrest.MatcherAssert を使ってるのか、
長いテストコードを素早く確認するのに、いちいち上までスクロールして確認なんて
やってられない、

import static org.junit.Assert.*;

とか

import static org.hamcrest.MatcherAssert.*;

assertThat を書くのも、個人的には、

MatcherAssert.assertThat(list1, CoreMatchers.is(list2));

MatcherAssert.assertThat(list1, CoreMatchers.hasItem("b"));

と、省略しない書き方の方が好みである。

Java11 でテキストファイルを String に読込み

Java11 でテキストファイルを String に読込むのは、とても記述が楽だ。

java.nio.file.Path に、java.nio.file.Files で対応できるのである。

サンプル
UTF-8 のファイル

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
Path path = Path.of(Thread.currentThread().getContextClassLoader().getResource("Sample.json").toURI());
String text = Files.readString(path, StandardCharsets.UTF_8);

URISyntaxException と、IOException を捕捉できるようにすれば良い。

SJIS のファイル

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
Path path = Path.of(Thread.currentThread().getContextClassLoader().getResource("Sample.json").toURI());
String text = Files.readString(path, Charset.forName("MS932"));