2016-09-09 1 views
1

テストをしていない従来のアプリケーションを扱う必要があります。したがって、リファクタリングを開始する前に、すべてがそのまま動作することを確認したいと思います。単体テストのパラメータとしてのAnyString()

ここで、次のような状況を想像してみてください。

public SomeObject doSomething(final OtherObject x, final String something) { 
    if(x == null) throw new RuntimeException("x may not be null!"); 
    ... 
} 

は今、私はそれが動作し、私はリファクタリングたら、私はそれを失うことはありません確かに、それはnullチェックをテストしたいです。

だから私は、これは当然のことながら働く、今、この

@Test(expected = RuntimeException.class) 
public void ifOtherObjectIsNullExpectRuntimeException() { 
    myTestObject.doSomething(null, "testString"); 
} 

をしました。

"testString"の代わりにランダムなStringを渡したいと思います。

だから私が試した:

しかし、これは許可されていない、私は

org.mockito.exceptions.misusing.InvalidUseOfMatchersException得るよう:。 を...あなたは検証の外で引数マッチャーを使用することはできませんかスタブしてください

私はこれの意味を理解していますが、私はテストなどをパラメータ化せずに私が望むことをやっていけるかどうかは疑問です。 私が使用できるライブラリは、Junit、AssertJ、Mockito、Powermockだけです。

アイデア?

答えて

1

Mockitoが例外を介してあなたに伝えようとしているように、それは実際にあなたが使用する方法ではありませんanyString。そのような方法はモックによってのみ使用される。

実際のランダムな文字列でテストしてみませんか?このようなシナリオで私の個人的なお気に入り:java.util.UUID.randomUUID().toString()。これにより、以前はあなたのテストには一度も使用されていなかったまったく新しい文字列が生成されます。

SomeObjectクラスのテストを書く場合は、SomeObjectの動作を邪魔しないようにしてください。あなたの例から、あなたはそれを正確に実行していませんでしたが、あなたがそのルートを下っているように見えました。実装自体ではなく、テストしようとしている実装の依存関係を模擬してください!これはとても重要です;それ以外の場合は、実際には何もテストしていません。

+0

これは文字列には有効ですが、たとえばロングや他のオブジェクト? – Sorona

+0

また、randomUUID()はnull afaikを返すことはないので、これは大きな欠点です。 – Sorona

+0

@Sorona [java.util.Random](https://docs.oracle.com/javase/7/docs/api/java/util/Random.html)を参照してください。ランダムな値でテストするために必要なものはすべてここにあります。また、ヌル値をテストする場合は、別の単体テストにする必要があります。単体テストは安価で速いと思われます。それが必要だと思う新しいテストケースを追加することを恐れてはいけません! – nasukkin

1

私はmockitoの知識はあまりありませんが、あなた自身のランダムな文字列ジェネレータをいつでも作成できます。多分それは働くことができ、それの入力のより多くのタイプを変更することができます

2

テストは決定論的でなければなりません。テストでランダムな値を使用すると、失敗したテストをデバッグするときの動作を再現することが困難になります。 "abcdefg"のように、テストの定数をStringとして作成することをお勧めします。

+0

私は多くのテストが決定論的でなければならないと同意しますが、パラメータ化されたテストが存在する理由があります。 TDDだけではなく、BDDでも可能です。テストスイートがすべての種類の可能な(そして「不可能な」)値を試して、テストが失敗するのを見るだけです。個人的に私は両方の見解の利点を見ています。 "プログラマが考えたテスト"のように確定的なテストに行く場合は、最も基本的な現実のシナリオでも常にカバーすることはできません。 – Sorona

+1

@Soronaパラメーター化されたテストは確かに決定的になります。 –

+0

彼らはそうかもしれませんが、いつもそうではありません。実際、あなたが頭をフレームワークとコンピュータサイエンスのランダム性の周りに置いているのであれば、おそらく常に「決定的なもの」です;)でも、私がここでやろうとしているのは、2番目のパラメータに関係なく必ず失敗することです。したがって、私は、特定のオブジェクトがそれに沿って来る場合、私の実装を壊さないという機会を強化したいと思います。テストは基本的に24時間365日実行されるので、統計的には... – Sorona

2

ここではコンセプトを混在させています。

anyStringのようなすべてのものを「モック」ヘルパー()モックオブジェクトを設定する際に使用されることを意図しています。

しかし、あなたはあなたのテストコードをチェックする場合:

@Test(expected = RuntimeException.class) 
public void ifOtherObjectIsNullExpectRuntimeException() { 
    myTestObject.doSomething(null, "testString"); 
} 

あなたは見つける:このテストに関わる全くないモックがあります。あなたは単にできませんその場所でそれらのMokito呼び出しを使用します。その場所に「モキトはありません」という理由があります。

ちょうど記録のために、とにかくここに船外に行く必要はありません。あなたのロジックはここで非常に明確です:最初の引数がnullの場合、その例外がスローされます。したがって、第二引数として来るものは本当に問題ではありません。ですから、第2引数でヌルをどのようにテストするかについて1時間考えると、私の目にはあなたの時間が無駄です。

最終ヒント:そこjava.lang.Objects され、そのクラスがnullのために素敵なチェックを持っているので、私の生産コードしかない

public SomeObject doSomething(final OtherObject x, final String something) { 
    Objects.requireNonNull(otherObject, "otherObject must not be null"); 
    Objects.requireNonNull(something, "something must not be null"); 

だけの違いのようになります。必要と...スローNullPointerExceptions

最終的に、最終的には、いくつかの人々はすべてのパラメータを最終決定することを提案します。しかし私はそれをしません。すべての症例の99%においての値を追加しています。これは、読み込むコードが増えたことを意味します。いい理由はありません。しかしそれはスタイルの問題です。潜在的な将来の変更を確認するためのテストを持っていることについてコメント

EDIT:あなたはそれを行うべきではありません。ある程度

  1. 、あなたの入力が確認された方法は、実装の詳細です。実装の詳細はテストしません。つまり、
  2. あなたのメソッドは一定の契約を結んでいます(たとえば、null入力でNPEをスローするjavadocを書いて非公式に指定する)。あなたのテストでは、が正確にであることを確認する必要があります。そして、契約は:最初の引数がnullの場合にスローされます。

さらに別の見方があります。私はまだあなたがここであなたの時間を無駄にしていると思うので!すべてのインターフェースが明確で、理解しやすく、使いやすいことを確認する必要があります。彼らはあなたのコードのユーザーが適切なことを簡単に行うことを許可します。彼が間違ったことをしないようにする。それはあなたが集中すべきものです - あなたのインターフェイス全体の品質! 今後の変更の可能性をテストする方法を心配するのではなく、コードベース全体が一貫していることを確認してください。

+0

事は、私はあなたに同意する。しかし、実際には、人々がコードを変更して、 'if(a)'の代わりに 'if(a &&!b)'例外をスローするようになったのです...テストをして、最初の引数がそのチェックで使用されます。 – Sorona