文書の過去の版を表示しています。
目次
Mocking Example
PowerMockを利用したexampleを残しておく。
Mocking Constructor
target classのコードの一部を次に示す。
public class SomeActionForm extends AbstractActionForm { ~~中略~~ //***** public method ***** @Override public ActionErrors validate(ActionMapping arg0, HttpServletRequest arg1) { ActionErrors _errors = new ActionErrors(); //do something return _errors; } }
このクラスは、struts1のActionFormクラスの一部である。
異常系テストとして、validationエラーメッセージを確認するために、ActionErrorsクラスをmockしたいケースである。
mockitoでは、constructorのmockクラスを作成できないため、PowerMockを利用する。
テストクラスコードの一部を次に示す。
@PrepareForTest({SomeActionForm.class}) public class TestSomeActionForm extends AbstractScreenTestCase { ~~中略 private void doCommonValidate(SomeActionForm form, List<String> errorCodeList) throws Exception { ~~中略 //mock ActionErrors ActionErrors _mockActionErrors = mock(ActionErrors.class); //new instanceで生成されるActionErrosインスタンスをmock objectに変換 whenNew(ActionErrors.class).withNoArguments().thenReturn(_mockActionErrors); ~~中略 } }
ここで注意したい部分は、@PrepareForTestだ。
テスト対象クラスではなく、mock対象のConstructorが存在するクラスを指定する。
複数個所がある場合は、カンマ区切りで指定する。
これだけでは、ActionErrorsのエラーメッセージが確認できない。
他にArgumetCaptorが必要なのだが、次節で説明する。
ArgumentCaptor
前節の続きで、ActionErrorsのエラーメッセージを確認するコードを次に示す。
private void doCommonValidate(SomeActionForm form, List<String> errorCodeList) throws Exception { //create Captor instances for ActionError parameters that will be added to the ActionErrors ArgumentCaptor<ActionError> _actionErrorCaptor = ArgumentCaptor.forClass(ActionError.class); //mock ActionErrors ActionErrors _mockActionErrors = mock(ActionErrors.class); //new instanceで生成されるActionErrosインスタンスをmock objectに変換 whenNew(ActionErrors.class).withNoArguments().thenReturn(_mockActionErrors); //call test method form.validate(actionMapping, request); //verify if the call add() to ActionErrors was made //and capture the ActionError that was passed verify(_mockActionErrors, atLeastOnce()).add(anyString(), _actionErrorCaptor.capture()); //get the capture ActionError and check the set values List<ActionError> _errors = _actionErrorCaptor.getAllValues(); //show error message for (ActionError _error : _errors) { assertTrue(errorCodeList.contains(_error.getKey()), "{unexpected error code = [" + _error.getKey() + "]}"); System.out.println(rsc(_error.getKey(), _error.getValues())); }//for }
ArgumentCaptorの基本使い方をを下に示す。
- 監視したいクラスをArgumentCaptorに渡す。
- テストメソッドをcallする。
- verifyメソッドで、監視クラスがcallされたかcheckする。
- ArgumentCaptorクラスのgetAllValues(複数の場合)か、getValue(単一)を利用して監視クラスを出力する。
Mocking static method
staticメソッドのmockクラスを作成したい場合は、mockStaticメソッドを利用する。
targetクラスの一部を下に示す。
public class DocumentShareSendMailService extends AbstractBaseSampleService { ~~中略 @Override protected void execute() { ~~中略 ExecutorService _threadPool = Executors.newFixedThreadPool(FIXED_THREAD_CNT); AsyncECabinetUploadUtil _util = new AsyncECabinetUploadUtil(_threadPool); ~~中略 } }
AysncECabinetUploadUtilクラスは、ExecutorServiceを使って非同期処理を行うクラスであるが、テストを実行しても実行されてないことに気づく。
本処理では、非同期処理だが、テストの際は同期処理にしたいというケースで、ExecutorServiceではなく、guavaモジュールに含まているMoreExecutorsクラスを利用する。
テストクラスのコード一部を次に示す。
@PrepareForTest({DocumentShareSendMailService.class}) public class TestDocumentShareSendMailService extends AbstractCustomTestCase { ~~中略 @Override protected void prepareSpecific() throws Exception { //mock Executors mockStatic(Executors.class); //wait until tasks are completed ExecutorService _mockExecutor = MoreExecutors.newDirectExecutorService(); when(Executors.newFixedThreadPool(anyInt())).thenReturn(_mockExecutor); } }
newDirectExecutorServiceメソッドがすぐにtaskを実行するExecutorServiceを返すため、テスト結果が確認できる。