はじめに
前回の記事では、OutSystemsのForgeで提供されている「Testing Framework」の基本的な使い方を紹介しました。
今回は一歩進んで、モックの作成方法を取り上げます。アクション・サイトプロパティ・SQL・現在時刻といった要素をモック化することで、テストをより柔軟かつ安定的に行えるようになります。
動作環境
- OutSystems(バージョン11)
- Testing Framework(バージョン4.1.1)
モックの使い方
■ アクション
アクションをモックするケースについて見ていきます。アクションをモックすると、以下のような利点があります。
-
依存処理を切り離せる
別モジュールの内部アクションをモックに差し替えれば、外部依存がない状態でテストできます。 -
動作を自由にシミュレートできる
「ユーザー情報が取得できる場合」「エラーを返す場合」などを簡単に再現できます。 -
本番環境の処理を安全に置き換えられる
決済処理や通知送信のような副作用のある処理を実際に実行しなくても検証できます。
Testing Framework では、アクションの種類ごとに以下のモックが用意されています。
-
MockAction
— ServerAction をモック -
MockExtensionAction
— ExtensionAction をモック(v5.1.1から対応) -
MockServiceAction
— ServiceAction をモック -
MockSystemActionGenerateGuid
— GenerateGuid SystemActionをモック
今回はServerActionのモックを作成します。
例: 外部APIを呼ぶアクションをモックする
例として、外部APIを呼ぶアクションをラップするアクションのテストシナリオを作成します。
テスト対象アクションの概要は以下の通りです。
-
GetUserInfo(内部アクション)
ログイン中のユーザー情報を取得する処理(本来は外部APIを参照) -
CreateTodoItem(公開アクション)
新規TODO作成時に GetUserInfo を呼んで「作成者」をセットします

GetUserInfoをモック対象として、テスト時にはダミーのユーザーIDを返すようにします。
モックを作成する
- ServerAction に「Mocks」フォルダを作成します
- Mocks フォルダーを右クリックし、「Add Server Action」を選択してアクションを追加します
- 引数と戻り値のシグネチャは、モック対象のアクションと一致させます
テストシナリオを作成
- BeginTestCase を配置してテスト要件を記載します
- MockAction を呼び出し、TargetAction を設定します
- TargetAction:
ActionRef({モック対象を含むモジュール名}, {モック対象アクション名})
- TargetAction:
- 作成したモックアクションを呼び出して実行します
- テスト対象アクションを実行します
- Assertions で期待値を検証します

MockContext
という名前の入力パラメータがある場合、テストで指定した MockContext
の値がモックアクション側で利用されます(モックの条件分岐などに活用できます)。
これでアクションのモックの流れは一通り確認できました。
■ サイトプロパティ
サイトプロパティをモックするケースを見ていきます。サイトプロパティをモックすると、以下の利点があります。
-
環境依存をなくせる
本番と開発で値が異なっても、モックにすれば統一した値でテストできます。 -
動的に設定を切り替えられる
上限値を2に設定して動作確認、といった柔軟な検証ができます。 -
テストケースの幅を広げられる
通常は再公開しないと変更できない値でもその場で切り替えることができます
サイトプロパティのモックは「MockSiteProperty〇〇」を利用します。型によって利用するモックアクションは異なります。
- Integer型:
MockSitePropertyInteger
- Text型:
MockSitePropertyText
- Boolean型:
MockSitePropertyBoolean
例: TODOの上限数を設定するサイトプロパティをモックする
例として、TODOの最大件数チェックするアクションのテストシナリオを作成します。
テスト対象アクションの概要は以下の通りです。
- サイトプロパティ: MaxTodoCount (Integer, デフォルト値: 100)
ユーザーに対して追加可能なタスクの上限数の設定値

- アクション: CanAddTodoItem
エンティティからそのユーザーのTODO件数を取得し、MaxTodoCount と比較を行い、追加可能なら True、上限超過なら False を返す

テストシナリオ作成
MaxTodoCount をモック対象として、テスト時に値の変更を行えるようにします。
- BeginTestCase を配置してテスト要件を記載します
- MockSitePropertyInteger を呼び出し、TargetSiteProperty を設定します
- TargetSiteProperty:
SitePropertyRef({モック対象を含むモジュール名}, {モック対象サイトプロパティ名})
- Value:
{テストで使用する値}
- TargetSiteProperty:
- テスト対象アクションを呼び出して実行します
- Assertions で期待値を検証します

以上がサイトプロパティのモックの要点になります。
■ SQL
SQLをモックするケースを見ていきます。SQLをモックすると、以下のような利点があります。
-
DB依存をなくせる
データがなくても「0件」「100件」など任意の結果を返せます。 -
テストデータ準備の工数を削減できる
本来はテスト用レコードをDBにINSERTしないといけませんが、モックで再現できます。 -
特定条件を自在に再現できる
「データが存在しない場合」「データが存在する場合」等をDBに触れず切り替えることができます。
SQLのモックはMockQueryResults
を利用します。
例:TODOの取得件数を取得するAggregateをモックする
サイトプロパティのモックでテスト対象としたアクションを例として利用します。
テストシナリオ作成
TODO件数を取得するAggregate「GetCountTasks」をモック対象として、テスト時に取得件数の変更を行えるようにします。
- BeginTestCase を配置してテスト要件を記載します
- MockQueryResults を呼び出し、TargetActionを設定します
- TargetAction:
ActionRef({モック対象を含むモジュール名}, {モック対象Aggregate名})
- Value:
{テストで使用するSQL結果}
- TargetAction:
- テスト対象アクションを呼び出して実行します
- Assertions で期待値を検証します

Aggregate 以外に、SQL や GetEntity Action もモックできます。
以上がSQLのモックの要点になります。
■ 現在時刻
現在時刻をモックするケースを見ていきます。現在時刻をモックすると、以下のような利点があります。
-
時間依存をなくす
CurrDate()
やCurrDateTime()
、CurrTime()
を固定値に置き換えできます。 -
未来や過去のシナリオを再現できる
任意の日付で動作確認ができます。 -
再現が難しいケースも検証できる
年末年始、月末締め、うるう年など特殊な条件も簡単に再現できます。
現在時刻のモックはMockCurrDateTime
を利用します。
例: TODOの期限と比較する現在日時をモックする
例として、期限切れのTODOがあるか判定するアクションのテストシナリオを作成します。
テスト対象アクションの概要は以下の通りです。
- アクション:HasExpiredTodos
エンティティから現在時刻と比較してタスクの期限が切れているTODOの件数を取得し、1件以上あれば True、なければ False を返します。

テストシナリオ作成
- BeginTestCase を配置してテスト要件を記載します
- MockCurrDateTime を呼び出し、Value を設定します
- Value:
{テストで使用する日付}
今回はOutSystems でサポートされている上限値である#3000-12-31#
をセット
- Value:
- テスト対象アクションを呼び出して実行します
- Assertions で期待値を検証します

Aggregate のフィルター内で CurrentDateTime()
を直接使用した場合、モック値が反映されずテストが期待どおり動作しませんでした。Aggregate のフィルターでは現在時刻を直接参照せず、一度変数に取り出して比較する等の回避策を検討してください。
以上が現在時刻をモックする際のポイントです。
おわりに
本記事では、アクション・サイトプロパティ・SQL・現在時刻のモック化方法を紹介しました。
Testing Framework ではまだ REST API のモックはサポートされていませんが、Extension Actions が v5.1.1 から対応されたように、今後さらにモック可能な範囲は広がっていくと考えられます。