#1.概要
HttpCalloutMock と StubProvider は同じ目的を果たします。
Apex ランタイム人事前に用意した擬似応答(偽物)を返却する。
HttpCalloutMockはクラス単位です。
StubProviderはメソッド単位です。
#2.HttpCalloutMockの使用パターン
0.HttpCalloutMockインターフェースを実装するクラス作成
1.テストデータ作成
2.Test.setMock
3.Test.startTest
4.テストメソッド起動
5.Test.stopTest
6.結果検証
#3.StubProviderの使用パータン
0.StubProvider インターフェースを実装するクラス作成
1.テストデータ作成
2.Test.createStub
※返却値は重要です。該当返却値しかモックできません。
3.Test.startTest
4.テストメソッド起動
5.Test.stopTest
6.結果検証
#4.お試し例
public class AnimalsCallouts {
public HttpResponse makeGetCallout() {
system.debug('makeGetCallout処理');
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
request.setMethod('GET');
HttpResponse response = http.send(request);
return response;
}
public HttpResponse makePostCallout() {
system.debug('makePostCallout処理');
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json;charset=UTF-8');
request.setBody('{"name":"mighty moose"}');
HttpResponse response = http.send(request);
return response;
}
}
@isTest
private class AnimalsCalloutsTest {
@isTest static void testGetCallout() {
Test.setMock(HttpCalloutMock.class, new AnimalsHttpCalloutMock());
Test.startTest();
AnimalsCallouts animalsCallout = new AnimalsCallouts();
HttpResponse response = animalsCallout.makeGetCallout();
System.debug('testGetCallout:' + response.getBody());
Test.stopTest();
String actualValue = response.getBody();
String expectedValue = '{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}';
System.assertEquals(actualValue, expectedValue);
}
@isTest static void testPostCallout() {
Test.setMock(HttpCalloutMock.class, new AnimalsHttpCalloutMock());
Test.startTest();
AnimalsCallouts animalsCallout = new AnimalsCallouts();
HttpResponse response = animalsCallout.makePostCallout();
System.debug('testGetCallout:' + response.getBody());
Test.stopTest();
String actualValue = response.getBody();
String expectedValue = '{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}';
System.assertEquals(actualValue, expectedValue);
}
@isTest static void testGetCalloutStub() {
AnimalsCallouts animalsCallout = (AnimalsCallouts)Test.createStub(AnimalsCallouts.class, new AnimalsCalloutStubProvider());
Test.startTest();
HttpResponse response = animalsCallout.makeGetCallout();
System.debug('testGetCalloutStub:' + response.getBody());
Test.stopTest();
String actualValue = response.getBody();
String expectedValue = '{"animals": ["000", "000", "000", "000", "000"]}';
System.assertEquals(actualValue, expectedValue);
}
@isTest static void testPostCalloutStub() {
AnimalsCallouts animalsCallout = (AnimalsCallouts)Test.createStub(AnimalsCallouts.class, new AnimalsCalloutStubProvider());
Test.startTest();
HttpResponse response = animalsCallout.makePostCallout();
System.debug('testPostCalloutStub:' + response.getBody());
Test.stopTest();
String actualValue = response.getBody();
String expectedValue = '{"animals": ["111", "111", "111", "111", "111"]}';
System.assertEquals(actualValue, expectedValue);
}
// HttpCalloutMockインターフェースを実装するクラス作成
private class AnimalsHttpCalloutMock implements HttpCalloutMock {
public HTTPResponse respond(HTTPRequest request) {
HttpResponse response = new HttpResponse();
response.setHeader('Content-Type', 'application/json');
response.setBody('{"animals": ["majestic badger", "fluffy bunny", "scary bear", "chicken", "mighty moose"]}');
response.setStatusCode(200);
return response;
}
}
// StubProvider インターフェースを実装するクラス作成
private class AnimalsCalloutStubProvider implements System.StubProvider {
public Object handleMethodCall(Object stubbedObject, String stubbedMethodName, Type returnType, List<Type> listOfParamTypes, List<String> listOfParamNames, List<Object> listOfArgs) {
if(stubbedMethodName == 'makeGetCallout') {
HttpResponse response = new HttpResponse();
response.setHeader('Content-Type', 'application/json');
response.setBody('{"animals": ["000", "000", "000", "000", "000"]}');
response.setStatusCode(200);
return response;
} else if (stubbedMethodName == 'makePostCallout') {
HttpResponse response = new HttpResponse();
response.setHeader('Content-Type', 'application/json');
response.setBody('{"animals": ["111", "111", "111", "111", "111"]}');
response.setStatusCode(200);
return response;
}
return null;
}
}
}
#5.Apex スタブ API の制限事項
Apex スタブ API を操作するときは次の点に注意してください。
- 模造されるオブジェクトは、Test.createStub() メソッドへのコールと同じ名前空間にある必要があります。ただし、StubProvider インターフェースの実装は別の名前空間でも構いません。
- 次の Apex 要素は模造できません。
- 静的メソッド (future メソッドを含む)
- 非公開メソッド
- プロパティ (getter および setter)
- トリガ
- 内部クラス
- システム型
- Batchable インターフェースを実装するクラス
- 非公開コンストラクタのみを持つクラス
- 戻り値の型またはパラメータの型としてイテレータは使用できません。
#6.参照
Use Mocks and Stub Objects
Apex REST コールアウト
スタブ API を使用したモックフレームワークの作成
Apex スタブ API を使用してテストクラスを作成する