私はJavaで抽象クラスをテストする必要があり、結果を提供するためにequals()
に依存するメソッドがあります。equals()に依存する抽象クラスのメソッドをMockitoでユニットテストする方法は?
public abstract class BaseClass<T extends BaseClass<T>> {
public boolean isCanonical() {
return toCanonical() == this;
}
public T toCanonical() {
T asCanonical = asCanonical();
if (equals(asCanonical)) {
//noinspection unchecked
return (T) this;
}
return asCanonical;
}
protected abstract T asCanonical();
}
あなたはtoCanonical()
メソッドが抽象メソッドasCanonical()
呼び出すasCanonical
ビルドで自分自身を比較する見ることができるように。
これをテストするには、抽象クラスの空の実装を作成し、実装された2つのメソッドの実際のメソッドを呼び出して、asCanonical()の独自のクラスを返します。これはequals()
方法ではなかった場合
BaseClass aCanonicalClass;
BaseClass aNonCanonicalClass;
@Mock
BaseClass sut;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// these are the methods under test, use the real ones
Mockito.when(sut.isCanonical())
.thenCallRealMethod();
Mockito.when(sut.toCanonical())
.thenCallRealMethod();
}
通常、私はちょうどこれを行うだろう:このエラーを与える
@Test
public void test_isCanonical_bad() {
// test true
Mockito.when(sut.equals(aCanonicalClass))
.thenReturn(true);
Mockito.when(sut.equals(aNonCanonicalClass))
.thenReturn(false);
Mockito.when(sut.asCanonical())
.thenReturn(aCanonicalClass);
Assert.assertTrue(sut.isCanonical());
// test false
Mockito.when(sut.equals(aNonCanonicalClass))
.thenReturn(true);
Mockito.when(sut.equals(aCanonicalClass))
.thenReturn(false);
Mockito.when(sut.asCanonical())
.thenReturn(aCanonicalClass);
Assert.assertFalse(sut.isCanonical());
}
を:
Mockitoの制限の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.
一つは、それはdoesnのことですequals()
とhashcode()
メソッドをモックすることができます。
回避策として、条件equals() = false
をテストするときに条件equals() = true
と別のランダムオブジェクトをテストするときには、自分自身を渡すだけです。
@Test
public void test_isCanonical() {
// test true
Mockito.when(sut.asCanonical())
.thenReturn(sut);
Assert.assertTrue(sut.isCanonical());
// test false
Mockito.when(sut.asCanonical())
.thenReturn(aCanonicalClass);
Assert.assertFalse(sut.isCanonical());
}
しかし、このテストでは、私がこれまでの実装を変更した場合でも渡す:
public T toCanonical() {
T asCanonical = asCanonical();
if (this == asCanonical) {
//noinspection unchecked
return (T) this;
}
return asCanonical;
}
かさえ、この:
public T toCanonical() {
return asCanonical();
}
間違っています!比較はequalsで行う必要があります。参照することと同じことではありません。
物事は私がtoCanonical()
方法を取得するときにテストすることは不可能で取得します。もちろん、これは動作しません
@Test
public void test_toCanonical_bad() {
// test canonical
Mockito.when(sut.equals(aCanonicalClass))
.thenReturn(true);
Mockito.when(sut.equals(aNonCanonicalClass))
.thenReturn(false);
Mockito.when(sut.asCanonical())
.thenReturn(aCanonicalClass);
Assert.assertSame(sut, sut.toCanonical());
// test non-canonical
Mockito.when(sut.equals(aNonCanonicalClass))
.thenReturn(true);
Mockito.when(sut.equals(aCanonicalClass))
.thenReturn(false);
Mockito.when(sut.asCanonical())
.thenReturn(aCanonicalClass);
Assert.assertNotEquals(sut, sut.toCanonical());
Assert.assertSame(aCanonicalClass, sut.toCanonical());
}
、と私はちょうどそれをテストしますので、実際には同じ回避策を適用することは理にかなっていません関数の戻り値は、asCanonical()
の一つである:事実を私はequals()
の結果を模擬することはできませんので
@Test
public void test_toCanonical() {
// test canonical
Mockito.when(sut.asCanonical())
.thenReturn(sut);
Assert.assertSame(sut, sut.toCanonical());
// test non-canonical
Mockito.when(sut.asCanonical())
.thenReturn(aCanonicalClass);
Assert.assertNotEquals(sut, sut.toCanonical());
Assert.assertSame(aCanonicalClass, sut.toCanonical());
}
両試験は無意味です。
私はそれを与えたオブジェクトで少なくともequals()
が呼び出されていますか? (スパイ)
これをテストする他の方法はありますか?
EDIT: this is a semplification of the actual code I'm working with.
I modified the example code to at least show the
toCanonical()
andasCanonical()
methods are supposed to return instances of the same class (and not just any class)I want to test the base class here. Only the concrete implementation know how to build an actual canonical class (
asCanonical()
) or check if this class is equal to a canonical class (equals()
). And please note thattoCanonical()
return ITSELF if it is equals to the canonical version of itself. Againequals != same
.The actual implementations are immutable classes. And since they are many and this code is the same for everyone i put it in a base class.
私はなぜあなたが 'BaseClass'の空でない実装を作成してそこにすべての必要なテストロジックを置くことができないのか分かりませんか?現在のところ、何らかの理由でMockitoを使わずにセットアップテストをすることを禁じているようです。 – user3707125
これは私のACTUALコードの簡略化されたコードであり、質問をすることができる範囲でそれを絞り込んだものです。私は 'BaseClass'の実装を一つも持っていません。私の抽象クラスをテストするには、何をするのだろうか?私は空の実装をテストしなければなりません。サブクラスが 'toCanonical()'をオーバーライドしたい場合は自由であり、独自のテストを行います。 –