/*
 * CB3ServiceTest.java
 * Copyright (C) 2008 Cyber Beans Corporation. All rights reserved.
 */
package jp.co.cybec.cb3.container.service;

import java.util.HashMap;

import jp.co.cybec.cb3.accessor.Accessor;
import jp.co.cybec.cb3.accessor.DataAccessContext;
import jp.co.cybec.cb3.container.service.CB3Service;
import jp.co.cybec.cb3.exception.AccessorUnknownException;
import jp.co.cybec.cb3.exception.ServiceException;
import jp.co.cybec.cb3.exception.ServiceExecutionException;
import jp.co.cybec.cb3.exception.ServiceRuntimeException;
import jp.co.cybec.cb3.mock.accessor.MockDataAccessContext;
import jp.co.cybec.cb3.mock.accessor.MockDataAccessContextThrowException;
import jp.co.cybec.cb3.session.RuntimeParameters;
import jp.co.cybec.cb3.session.ServiceParameters;
import junit.framework.Assert;

import org.junit.Test;


/**
 * CB3Serviceのテストケース。
 * @author Naoko Sugimoto
 */
public class CB3ServiceTest {

	/**
	 * {@link jp.co.cybec.cb3.container.service.CB3Service#setDataAccessContext(jp.co.cybec.cb3.accessor.DataAccessContext)} のためのテスト・メソッド。
	 * setDataAccessContext()によりデータアクセスコンテキストをセットした後、
	 * getDataAccessContext()によりデータアクセスコンテキストを取得できることを確認する。
	 */
	@Test
	public void testSetDataAccessContext() {

		// サービスを生成。
		CB3Service cB3Service = new CB3Service() {
			protected int doService(ServiceParameters serviceParameters, RuntimeParameters runtimeParameters) {
				return 0;
			}
		};

		// データアクセスコンテキストをセット。
		MockDataAccessContext dataAccessContext = new MockDataAccessContext(new HashMap<String, Accessor>());
		cB3Service.setDataAccessContext(dataAccessContext);
		// データアクセスコンテキストを取得。
		Assert.assertEquals(dataAccessContext, cB3Service.getDataAccessContext());
	}

	/**
	 * {@link jp.co.cybec.cb3.container.service.CB3Service#callService(jp.co.cybec.cb3.session.ServiceParameters, jp.co.cybec.cb3.session.RuntimeParameters)} のためのテスト・メソッド。
	 * メソッドを実行し、戻り値を確認する。
	 */
	@Test
	public void testCallService() {

		// サービスを生成。
		CB3Service cB3Service = new CB3Service() {
			protected int doService(ServiceParameters serviceParameters, RuntimeParameters runtimeParameters) {
				return 0;
			}
		};

		// データアクセスコンテキストをセット。
		MockDataAccessContext dataAccessContext = new MockDataAccessContext(new HashMap<String, Accessor>());
		cB3Service.setDataAccessContext(dataAccessContext);

		// サービスを実行。
		int returnCode = cB3Service.callService(new ServiceParameters(), new RuntimeParameters(null));

		// 戻り値をチェック。
		Assert.assertEquals(0, returnCode);

		// データアクセスコンテキストのリリースが呼ばれていることを確認。
		Assert.assertTrue(dataAccessContext.isReleased());
	}

	/**
	 * {@link jp.co.cybec.cb3.container.service.CB3Service#callService(jp.co.cybec.cb3.session.ServiceParameters, jp.co.cybec.cb3.session.RuntimeParameters)} のためのテスト・メソッド。
	 * ビジネスロジック内で例外が発生したとき、{@link ServiceRuntimeException}に置き換えて
	 * 投げられることを確認する。
	 */
	@Test
	public void testCallServiceCatchException() {

		// サービスを生成。
		CB3Service cB3Service = new CB3Service() {
			protected int doService(ServiceParameters serviceParameters, RuntimeParameters runtimeParameters) throws ServiceException {
				throw new ServiceException("例外のテストです。");
			}
		};
		// データアクセスコンテキストをセット。
		MockDataAccessContext dataAccessContext = new MockDataAccessContext(new HashMap<String, Accessor>());
		cB3Service.setDataAccessContext(dataAccessContext);

		// サービスを実行。
		try {
			cB3Service.callService(new ServiceParameters(), new RuntimeParameters(null));
			Assert.fail();
		} catch (ServiceExecutionException e) {
			System.out.println(e.getCause());
			if (e.getCause() instanceof ServiceException) {
				// 想定どおり
			} else {
				Assert.fail();
			}
		}
	}

	/**
	 * {@link jp.co.cybec.cb3.container.service.CB3Service#callService(jp.co.cybec.cb3.session.ServiceParameters, jp.co.cybec.cb3.session.RuntimeParameters)} のためのテスト・メソッド。
	 * アクセッサのリリース処理で例外が発生したとき、{@link ServiceRuntimeException}に置き換えて
	 * 投げられることを確認する。
	 */
	@Test
	public void testCallServiceCatchAccessorException() {

		// サービスを生成。
		CB3Service cB3Service = new CB3Service() {
			protected int doService(ServiceParameters serviceParameters, RuntimeParameters runtimeParameters) {
				return 0;
			}
		};

		// データアクセスコンテキストをセット。
		DataAccessContext dataAccessContext = new MockDataAccessContextThrowException(new HashMap<String, Accessor>());
		cB3Service.setDataAccessContext(dataAccessContext);

		// サービスを実行。
		try {
			cB3Service.callService(new ServiceParameters(), new RuntimeParameters(null));
			Assert.fail();
		} catch (ServiceExecutionException e) {
			if (e.getCause() instanceof AccessorUnknownException) {
				// 想定どおり
			} else {
				Assert.fail();
			}
		}
	}
}
