質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.34%

LocalDate.now()を使用しているメソッドのテストの方法

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 3,712

score 7

前提・実現したいこと

「本日を含む年から10年間の年を取得する」という機能を持つ
LocalDate.nowを使用したメソッドのテストを作成しているのですが、
下記のようなエラーメッセージが出ました。

発生している問題・エラーメッセージ

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

テスト対象のメソッド

public class ClassificationUtil {
    public static List<OptionValueText> createYearList() {
        int currentYear = LocalDate.now().getYear();
        List<OptionValueText> resultList = new ArrayList<OptionValueText>();
        for (int year = currentYear - 9; year <= currentYear; year++) {
            resultList.add(new OptionValueText(String.valueOf(year), String.valueOf(year)));
        }
        return resultList;
    }
}

テストしたいこと

/** 年月"年"に当年含む過去10年を正しく得られるかをテストしたい */
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassificationUtil.class, LocalDate.class})
@SpringBootTest
class ClassificationUtilTest {
    @Test
    void createYearList() {
        LocalDate dummy = LocalDate.of(2018, 1, 1);
        PowerMockito.spy(LocalDate.class);
        PowerMockito.when(LocalDate.now()).thenReturn(dummy);

        List<OptionValueText> optionValueTextList = ClassificationUtil.createYearList();

        assertEquals("2009", optionValueTextList.get(0).getValue());
    }
}

試したこと

以前類似の質問があったので、
https://teratail.com/questions/141410
を参考にテストコードを書きましたがエラーになってしまいます。

補足情報(FW/ツールのバージョンなど)

・mockitoを使用した他のメソッドのテストは問題なく動作しています
環境:SpringBoot、Meiven、IntelliJ、Thymeleaf

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

動作確認環境

  • OpenJDK 11.0.2
  • JUnit 4.12
  • Mockito 2.23.4
  • PowerMock 2.0.4

この環境と下記のテストコードで一応テストは通りました。参考になりますでしょうか。

import static org.junit.Assert.*;

import java.time.LocalDate;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassificationUtil.class})
public class ClassificationUtilTest {

    @Test
    public void createYearListTest() {
        LocalDate dummy = LocalDate.of(2018, 1, 1);
        PowerMockito.mockStatic(LocalDate.class);
        PowerMockito.when(LocalDate.now()).thenReturn(dummy);

        List<OptionValueText> optionValueTextList = ClassificationUtil.createYearList();

        assertEquals("2009", optionValueTextList.get(0).getValue());
    }

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/01 09:11 編集

    補足的な情報です。
    `mockStatic()` を使う場合、 `ClassificationUtil` 内で `LocalDate.now()` の前に `LocalDate.of()` などの処理が動くような時は、 `NullPointerException` にならないように テストクラスで実際のメソッドを呼ぶように定義することも必要です。
    ```Java
    PowerMocito.when(LocalDate.of(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenCallRealMethod();
    ```
    念のため。

    キャンセル

  • 2019/11/01 14:07

    JUnitのヴァージョンの問題だったようで、JUnit5からJunit4に変更したところ問題なくテストが通りました。ご回答及び補足情報をいただいた方々、ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る