【SAPUI5】Mock Serverの設定を一からやってみる

##Mock Serverとは
Mock Serverとは、ODataを模したレスポンスを返すためのJSファイルです。Mock Serverを使うことにより、ODataサービスが利用できないときでも開発を進めることができます。（GETリクエストにのみ対応しており、データの更新はできません）

WebIDEでテンプレートからODataを使うアプリを作ると、自動的にlocalServiceというフォルダが登録され、必要なファイルが用意されています。
ただし、今回はMock Serverの仕組みについて知るために一から設定してみたいと思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/74939fe8-228b-41fc-458e-77b0ec210cd1.png)

##Mock Serverを呼ぶための構成

Mock Serverを呼ぶための構成は以下のようになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/9ad548e4-5f66-ac3c-2dce-5835792476d0.png)

**flpSandboxMockserver.html**というファイルが最初に実行され、ここから**mockserver.js**が呼ばれます。このファイルがMock Serverとして機能し、ODataに代わってモックデータを返します。mockserver.jsは**metadata.xml**を参照し、metadataに定義されたEntity Setの構造、型に合わせたデータを返します。
mockdataフォルダにテストデータを入れておくと、そのデータが使われます。データがない場合、自動的にランダムなデータが生成されます。

##Mock Serverの設定手順
まずはベースになるFiori Appを作成し、次にMock Serverの設定を行います。
###1. ベースになるFiori Appを作成
####1-1. 簡単なODataサービスを作成
metadataは以下のようになります。

```xml
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" Version="1.0">
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="Z_MOB58_06_SIMPLEDATA_SRV" xml:lang="en" sap:schema-version="1">
<EntityType Name="SalesOrder" sap:content-version="1">
<Key>
<PropertyRef Name="SoId"/>
</Key>
<Property Name="SoId" Type="Edm.String" Nullable="false" MaxLength="10" sap:unicode="false" sap:label="Sales Order ID" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
<Property Name="CreatedAt" Type="Edm.DateTime" Nullable="false" Precision="7" sap:unicode="false" sap:label="Time Stamp" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
<Property Name="Note" Type="Edm.String" Nullable="false" MaxLength="255" sap:unicode="false" sap:label="Description" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
<Property Name="CurrencyCode" Type="Edm.String" Nullable="false" MaxLength="5" sap:unicode="false" sap:label="Currency Code" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" sap:semantics="currency-code"/>
<Property Name="GrossAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:unicode="false" sap:unit="CurrencyCode" sap:label="Gross Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
</EntityType>
<EntityContainer Name="Z_MOB58_06_SIMPLEDATA_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
<EntitySet Name="SalesOrderSet" EntityType="Z_MOB58_06_SIMPLEDATA_SRV.SalesOrder" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:content-version="1"/>
</EntityContainer>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="self" href="http://sts4csrvr.st.com:8001/sap/opu/odata/sap/Z_MOB58_06_SIMPLEDATA_SRV/$metadata"/>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="latest-version" href="http://sts4csrvr.st.com:8001/sap/opu/odata/sap/Z_MOB58_06_SIMPLEDATA_SRV/$metadata"/>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
```
####1-2. Fiori Appを登録
SAPUI5 Applicationのテンプレートから登録します。このテンプレートでは必要最小限のファイルしか作られないので、今回の目的に合っています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/8bfa91d4-79e5-fcc8-84b6-7fed9aaaea03.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/8780b48e-2a9f-e0f0-a5e3-4f760c5a7d3b.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/4e5117bb-ee2a-e9ad-ae3b-846bfadf9d5b.png)

####1-3. ODataとの接続
まずはODataにつないで実行するため、以下の手順で接続設定をします。（Master Detailなどのテンプレートを使えば自動的に設定されます）

**manifest.json**
データソースに1-1で定義したODataサービスを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/7752d0d8-0f25-ab92-e630-8fa2e4b0a216.png)

上記のODataをデフォルトモデルに設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/38586a30-858d-6cb7-400a-5fa42c224522.png)

**neo-app.json**
ODataの実際の接続先を定義します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/7700f4b9-5e0e-e58b-406e-28b14b70e01a.png)

neo-app.jsonで指定する宛先は、あらかじめSAP Cloud Cockpitで登録しておきます。（参考：[OData(7) ODataを使ったSAPUI5アプリケーションの作り方 準備編](https://qiita.com/tami/items/510a28655ee1af6254ea)）
neo-app.jsonで宛先を指定するのは、開発環境、テスト環境などバックエンドが変わるたびにmanifest.jsonを変更する必要がないようにするためです。manifest.jsonで直接に宛先を指定してもちゃんと動きます。

/webappを先頭につけたresoucesを追加
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/5c3cc251-9c27-58af-5a31-16ad61dd9fbb.png)
もともと/resoucesと/test-resourcesというパスが設定されていますが、これらをコピーして頭に/webappとつけます。このあと定義するflpSandboxMockserver.htmlからリソースを読み込むために必要な設定となります。

####1-4. ビューを作成
SalesOrderのリストを表示するシンプルなビューを作ります。

```xml
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="train.Train_02_MockServer.controller.SalesOrder" displayBlock="true">
	<Shell id="shell">
		<App id="app">
			<pages>
				<Page id="page" title="{i18n>title}">
					<content>
					    <List items="{/SalesOrderSet}">
					        <items>
					            <StandardListItem type="Navigation" title="{SoId}" description="{GrossAmount} {CurrencyCode}"/>
					        </items>
					    </List>
					</content>
				</Page>
			</pages>
		</App>
	</Shell>
</mvc:View>
```
####1-5. 実行してみる
このような結果になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/3805aba5-dbf0-bcf2-e317-41497ad243ec.png)

###2. Mock Serverの設定
次に、Mock Serverの設定を追加します。

####2-1. metadata.xmlファイルを配置
ODataサービスのmetadataをダウンロードしたものを用意します。
webapp配下にlocalServiceというフォルダを作って、metadata.xmlファイルを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/b76a3701-3348-07cb-945d-71a33ab05000.png)
Edit->Beautyをすると見やすい形式になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/33afd1a7-a616-17ee-7443-760cec413480.png)

####2-2. mockserver.jsを作成
localServiceフォルダ配下にmockserver.jsファイルを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/dcf88f81-2226-a75c-2669-4439f7182eaf.png)


```javascript
sap.ui.define(
	["sap/ui/core/util/MockServer"],
	function(MockServer){
		var oMockServer;
		return{
			init: function(){
				oMockServer = new MockServer({
					//manifest.jsonで定義したdataSourcesのuriと同じ
					rootUri: "/S4C/sap/opu/odata/sap/Z_MOB58_06_SIMPLEDATA_SRV/"
				});
				
				//自動的にレスポンスを返すための設定
				MockServer.config({
					autoRespond: true,
					autoRespondAfter: 1000
				});
				
				//metadata.xmlへのパス
				var sPath = jQuery.sap.getModulePath("train.Train_02_MockServer.localService");
				var sMetaPath = sPath + "/metadata.xml";

				oMockServer.simulate(sMetaPath, {
					//モックデータのパス
					sMockdataBaseUrl: sPath + "/mockdata",
					//データがなかったら自動生成する
					bGenerateMissingMockData: true
				});
				//Mockサーバーを起動
				oMockServer.start();
			}
		};
	}
);
```


####2-3. flpSandboxMockserver.htmlを作成
testフォルダ配下にflpSandboxMockData.htmlを作成します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/855081cc-5db3-c651-affd-9928ede1aeb7.png)

まずは以下のように骨組みを作ります。

```html
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Train_02_MockServer</title>
		<script id="sap-ui-bootstrap"
				src="../resources/sap-ui-core.js"
				data-sap-ui-libs="sap.ushell, sap.collaboration, sap.m, sap.ui.layout, sap.f"
				data-sap-ui-theme="sap_belize"
				data-sap-ui-preload="async"
				data-sap-ui-compatVersion="edge"
				data-sap-ui-resourceroots='{"train.Train_02_MockServer": "../"}'
				data-sap-ui-frameOptions='allow'> // NON-SECURE setting for testing environment
		</script>		
	</head>
	<body class="sapUiBody" id="content">
	</body>
</html>
```
bootstrapの部分で通常のindex.htmlファイルと異なるのは以下の点です。

- ライブラリにsap.ushell, sap.collaborationを追加する
    - Fiori Launchpad（タイルなど）を表示するのに必要
- resourcerootsの階層が、通常("./")よりも一段下になる
    - このファイルが通常よりも1階層下であるlocalServiceの下に置かれるため

続いてbootstrapの上に以下のコードを追加します。
Fiori Launchpad Sandbox(Fiori Launchpadのテスト用ローカル環境)を実行するための設定です。

```javascript
		<script>
			window["sap-ushell-config"]= {
				defaultRenderer: "fiori2",
				renderers: {
					fiori2: {
						componentData: {
							config: {
								search: "hidden"
							}
						}
					}
				},
				applications: {
					"SalesOrder-display": {
						additionalInformation: "SAPUI5.Component=train.Train_02_MockServer",
						applicationType: "URL",
						"url": "../",
						description: "Search sales orders",
						title: "Sales orders"
					}
				}
			};
		</script>
		<script src="../test-resources/sap/ushell/bootstrap/sandbox.js"></script> 
```
最後に、bootstrapの下に以下のコードを追加します。
mockserverを起動し、Fiori Launchpad Sandboxを実行するためのコードです。

```javascript
		<script>
			sap.ui.getCore().attachInit(function(){
				sap.ui.define(["train/Train_02_MockServer/localService/mockserver"],
				function(mockserver){
					mockserver.init();
				});
				sap.ushell.Container.createRenderer().placeAt("content");
			});
		</script>
```
##Mock Serverで実行
###Run Configuration
Mock Serverで実行するため、Run Confgurationを開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/d48231c7-952d-8bfa-de7e-13f54fd6151a.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/df0f91d7-0097-5c98-f4b3-f364b3d3832e.png)
実行するファイルとしてflpSandboxMockserver.htmlを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/051d93f5-6b9b-b3fc-a017-4cd818f32a87.png)
Save and Runを押して実行します。

実行結果は以下のようになります。
Fiori Launchpad風の画面が開きました。これがFiori Launchpad Sandboxです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/bf34b91b-4244-3909-fbd9-c5c6fea5fb23.png)
タイルをクリックするとデータが表示されます。これは自動生成されたデータです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/62f5386f-f510-8608-3efd-2515b4eceef9.png)

##テストデータの作り方
テストデータの作り方として、2つの方法があります。

1. 実際のODataをダウンロードしたものを使う
2. metadata.xmlから生成する

###1. 実際のODataをダウンロードしたものを使う方法
ブラウザなどでEntity Setを取得するクエリを実行し、結果をjsonファイルに保存します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/6cf02cde-9fe3-2c8f-0d2c-80335cacd36b.png)

localService配下にmockdataというフォルダを作り、ダウンロードしたファイルをインポートします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/98372b04-50cb-fdea-0516-65c3eaaf4366.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/a55beb4d-0102-bf32-acab-88cfd4841739.png)

####実行結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/8ae075a3-a6bb-9330-1922-80fb1b657e60.png)


###2. metadata.xmlから生成する方法
metadata.xmlファイルを右クリックし、Edit Mock Dataを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/9512b80b-9bee-16df-ab3b-ab43ca335227.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/4f55ad80-9a13-e6cf-a750-857e540bf39c.png)
必要に応じてデータを変更し、OKを押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/64e68d98-e0e3-049c-306a-1dc014c6e1ff.png)

####実行結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/03063732-0f4b-3600-cd49-2850b7e53870.png)

##感想
今回は一から作ったためつまづきも多く苦労しましたが、実際にはすべてのファイルが自動生成されるため、すぐに使うことができるはずです。

Mock Serverを使えば社外などバックエンドにつなげない環境からでもFiori Appを開発できるようになるので、在宅勤務の可能性が広がるのではないかと思いました。（希望）