私は継承されたコードに少し取り組んでいます。 NullPointerExceptionをキャッチするはずのテストを作成しました(nullオブジェクトからメソッドを呼び出そうとしているため)
@Test(expected=NullPointerException.class)
public void checkXRequirement_NullProduct_AddAction_ShouldThrowNullPointerException() throws CustomException {
Site site = mock(Site.class);
Product product = null;
when(BasketHelper.getAction(request)).thenReturn(0);
when(BasketHelper.getActionProduct(site, request)).thenReturn(product);
BasketHelper.requiresX(request, site);
}
関連するメソッドと変数:
public static final int ACTION_ADD = 0;
public static final int ACTION_DELETE = 1;
protected static int getAction(HttpServletRequest a_request) {
String sBuyProduct = a_request.getParameter(ATTRIBUTE_NAME_BUY_PRODUCT);
String sBuyProduct = a_request.getParameter(ATTRIBUTE_NAME_BUY_PRODUCT);
if (sBuyProduct != null) iAction = ACTION_ADD;
else (sDelProduct != null) iAction = ACTION_DELETE;
return iBasketAction
}
protected static Product getActionProduct(Site a_site, HttpServletRequest a_request) {
String sBuyProduct = a_request.getParameter(ATTRIBUTE_NAME_BUY_PRODUCT);
String sDelProduct = a_request.getParameter(ATTRIBUTE_NAME_DEL_PRODUCT);
String sProduct = null;
switch (getBasketAction(a_request)) {
case BASKET_ACTION_ADD:
sProduct = sBuyProduct;
break;
case BASKET_ACTION_DELETE:
sProduct = sDelProduct;
break;
}
int iProductId;
try {
iProductId = Integer.parseInt(sProduct);
} catch (NumberFormatException nbrEx) {
return null;
}
Product prod = getProductById(iProductId);
if (prod.isMasterProduct()) {
prod = getChildProduct(prod, a_site, a_request);
}
return prod;
}
public static boolean requiresX(HttpServletRequest request, Site site) throws CustomException {
try{
if (getAction(request) == ACTION_ADD) {
Product prod = getActionProduct(site, request);
return prod.getType().isRequiredX();
}
} catch(NullPointerException exception) {
log.error("Error Message", exception);
}
return false;
}
テストを実行したjUnitの結果は、以下のスタックトレースの失敗です。
Java.lang.Exception: Unexpected exception, expected<Java.lang.NullPointerException> but was<org.mockito.exceptions.misusing.WrongTypeOfReturnValue>
Caused by: org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Integer cannot be returned by getParameter()
getParameter() should return String#
ここでwhen()。thenReturnがどのように機能するかを誤解していますか? getActionが0を返し、getActionProductが呼び出されているときは常にnullを返します。明らかにgetParameter()が呼び出され、その理由が正確にわかりません。
Mockitoは静的メソッドをモックできません。 whenチェックが無効です:
when(BasketHelper.getAction(request)).thenReturn(0);
when(BasketHelper.getActionProduct(site, request)).thenReturn(product);
これは、モックするのが難しいため、静的メソッドの使用を減らしたいもう1つの理由です。
クラスがこのままである場合、動作を模擬する簡単な方法はありません。ただし、デザインを変更して両方の方法を非静的にしたい場合。 「いつ」を使用する正しい方法は、モックされたオブジェクトにチェックを適用することです。例えば:
BasketHelper basketHelper = mock(BasketHelper.class);
when(basketHelper.getAction(request)).thenReturn(0);
when(basketHelper.getActionProduct(site, request)).thenReturn(product);
ただし、これは、クラスのgetActionメソッドとgetProductメソッドを非静的に再設計した場合にのみ機能します。
静的メソッドのモックをサポートする他のテストフレームワークがいくつかあることを覚えています。
PowerMockを使用できます。まず、静的メソッドを呼び出すクラスのモックを作成します-
mockStatic(BasketHelper.class);
次に、スタブを定義します-
when(BasketHelper.getAction(request)).thenReturn(0);
when(BasketHelper.getActionProduct(site, request)).thenReturn(product);
静的メソッド、プライベートメソッド、またはコンストラクタをモックすることは、適切なコーディング方法ではありません。しかし、いくつかのレガシーコードがあり、それをモックする必要がある場合。その場合、mockitoでPowermockを使用できます。
Powermockを使用して静的メソッドをモックする場合の手順。
1)特定のランナー、つまりPowerMockRunner.classを使用します。
2)アノテーションを使用@ PrepareForTest(UtilityClass.class)。
3)静的メソッドを含むユーティリティクラスを初期化します。
4)必要なモック静的メソッド。
@RunWith(PowerMockRunner.class)
@PrepareForTest
public class mockingStaticMethod(){
@Mock
Dependency dependency;
@InjectMocks
SystemUnderTest systemUnderTest;
@Test
public void testStaticMethod(){
PowerMockito.mockStatic(Utility.class);
When(UtilityClass.staticMethod(arguments)).thenReturn(expectedValue);
result = systemUnderTest.methodCallingStaticMethod();
assertEquals(expectedValue, actualValue);
}
}
これは、注釈を使用する他の人を助けるかもしれません。アノテーションを使用している場合、@ InjectMocksの代わりに@Mockを使用する必要があるかもしれません。 @InjectMocksは@Spyと@Mockの両方として機能するためです。また、@ Spyは最近実行されたメソッドを追跡しているため、誤ったデータが返されたり、サブベッドされたりする場合があります。次の2つを確認してください。
https://groups.google.com/forum/?fromgroups#!topic/mockito/9WUvkhZUy9
テストで同じ問題を修正しようとしているときに、このスレッドに遭遇しました。
他の人がこの問題を見つけてここに到達した場合...私の場合は、サポートクラスに@PrepareForTestアノテーションを使用していないことが原因です。