4

NullPointerException をスローするこのコードがあります

NumberFormat formatterFake = mock(NumberFormat.class);  
when(formatterFake.format(1)).thenReturn("1");

問題は、when() メソッド内で例外が発生することです。

java.lang.NullPointerException
    at java.text.NumberFormat.format(NumberFormat.java:297)

また、具象クラスをモックしようとしましたが、同じ結果が得られました。

NumberFormat formatterFake = mock(DecimalFormat.class); 

私はMockitoの初心者であり、どんな助けも非常に期待されています. 前もって感謝します。

4

2 に答える 2

4

何が起こっていますか

OK、モックでメソッドをスタブするために、ここですべてを行っています。

NumberFormat抽象クラスです。Mockito は通常のクラスと同じように抽象クラスをモックできるため、これは通常は問題ありません。問題は、メソッドの実装に関係していますNumberFormat#format(long)

Oracle jdk 1.7.0 update 2 を使用している実装のソース コードを見ると、このメソッドが何をするかがわかります。

public final String format(long number) {
        return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString();
    }

NumberFormat#format(long, StringBuffer, FieldPosition)あなたが嘲笑しているフォーマットメソッドは、実際には同じ抽象クラスにある別のフォーマットメソッドを呼び出しています。次に、そのtoString()呼び出しの結果の結果を呼び出した結果を返します。これは、Mockito がスタブできないFINALメソッドです。

when-then 構文を使用してメソッドをスタブすると、Mockito はスタブしているメソッドを実際に呼び出します (最終的な実装がある場合)。だからあなたが書くとき:

when(formatterFake.format(1))

実際にformatは、抽象NumberFormatクラスに実装されたメソッドの最初のオーバーロードを呼び出しています。

の 1 番目のオーバーロードの最終的な実装は、2 番目のメソッドをformat呼び出します。formatその 2 番目format は の抽象メソッドですNumberFormat。したがって、呼び出す実装はありません。

問題ありません。モックを使用しています。Mockito は、モック内の未実装のメソッドごとにデフォルトのスタブを提供します。 デフォルトでは、値を返すすべてのメソッドに対して、モックは null、空のコレクション、または適切なプリミティブ/プリミティブ ラッパー値を返します (例: int/Integer、boolean/Boolean の場合は 0、false、...)。

したがって、 への呼び出しをスタブしようとすると、実装があるため、を返すNumberFormat#format(long)デフォルトのスタブを呼び出すことになり、それが-ed になり、そこに原因の NPE があります。NumberFormat#format(long, StringBuffer, FieldPosition)null.toString()

ソリューション

通常、クラスを直接モックするのではなく、インターフェイスをモックします。これにより、最終的なものがないため、この種の問題の可能性を完全に回避できます。ただし、ここではモックに使用できるインターフェイスがないため、オプションではありません。

format の 3 引数のオーバーロードを直接モックできます。これにより、必要に応じて format の引数が 1 つのバージョンを呼び出すことができるようになります。

  @Test
  public void test() {
    final NumberFormat mockFormatter = mock(NumberFormat.class);

    final StringBuffer buffer = new StringBuffer("1");
    when(mockFormatter.format(anyLong(), any(StringBuffer.class), any(FieldPosition.class))).thenReturn(buffer);

    System.out.println("Result: " + mockFormatter.format(1));
  }

ただし、これが最善の解決策であるかどうかはわかりません。たぶん、他の誰かが体重を量るでしょう。

編集:

Garrett Hall の回答を見た後、実装について話しているときは最終的な実装を意味していることをより明確にしました。

彼が示唆するように、PowerMock では、最終的なフォーマット メソッドを直接モックすることができます。

于 2012-05-15T13:53:43.360 に答える
2

最終メソッドをモックするには、 PowerMockを使用する必要があります。

クラスの最終メソッドをモックする必要がある理由がわかりませんNumberFormat。これはテストの匂いです。テストも投稿してください。

于 2012-05-15T14:46:06.793 に答える