/**
* @Created May 8, 2012 5:13:50 PM
* @author cry30
*/
package com.philip.journal.home.service;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Date;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.philip.journal.common.BeanUtils;
import com.philip.journal.core.Constant;
import com.philip.journal.core.JournalTestCommon;
import com.philip.journal.core.bean.AbstractAuditableBean;
import com.philip.journal.core.bean.User;
import com.philip.journal.core.exception.JournalException;
import com.philip.journal.core.service.AbstractPowerMockJournalTestService;
import com.philip.journal.home.bean.Branch;
import com.philip.journal.home.bean.Entry;
import com.philip.journal.home.dao.BranchDAO;
import com.philip.journal.home.dao.EntryDAO;
/** Test class for {@link XmlHelper}. */
@PrepareForTest({
BeanUtils.class,
XPathFactory.class })
public class XmlHelperTest extends AbstractPowerMockJournalTestService<XmlHelper> {
/** Test artifact. First Root Branch. */
static final long TEST_ID_RTBRANCH1 = 2L;
/** Test artifact. Sub Branch 1. */
static final long TEST_ID_SUBBRANCH1 = 3L;
/** Test artifact. Count of Test Entries. */
static final int TEST_ENTRY_COUNT = 3;
/** Test artifact. Invalid ID. */
static final long TEST_BOGUS_ID = 123;
/** Test artifact. Count of Test Branches. Root not included. */
static final int TEST_BRANCH_COUNT = 2;
/** Test artifact. Mocked Document */
private transient Document mockDocument;
/** Test artifact. Element of Branch under Root. */
private transient Element testRootBranchEl = mock(Element.class);
/** Test artifact. Branch under root. */
private transient Branch testBranch1;
/** Test artifact. Root Branch Element. */
private transient Element testBranchEl1 = mock(Element.class);
/** Test artifact. Root Branch Element. */
private transient Element testBranchesEl1 = mock(Element.class);
/** Test artifact. */
private transient Branch testSubBranch1;
/** Test artifact. */
private transient Element testSubBranchEl1 = mock(Element.class);
/** Test artifact. */
private transient Element testSubBranchesEl1 = mock(Element.class);
/** Test artifact. */
private transient NodeList testBranchList1 = mock(NodeList.class);
/** Test artifact. */
private transient NodeList testBranchList2 = mock(NodeList.class);
//TODO: Test for these methods.
// /** Test artifact. */
// private transient NodeList testEntryList1 = mock(NodeList.class);
// /** Test artifact. */
// private transient NodeList testEntryList2 = mock(NodeList.class);
/** Test artifact. XPath instance. */
private final transient XPath mockXPath = mock(XPath.class);
/** Spy Instance. */
private transient XmlHelper spyInstance;
/**
* Java Beans Setup: <br/>
* 1 Root Branch. <br/>
* 1 Sub branch under Root branch. <br/>
* 2 Entries under the Root branch. <br/>
* 1 Entry for the sub Branch.
*
* <pre>
* \Branch1
* \Entry1.txt
* \Entry2.txt
* \SubBranch1
* \Entry3.txt
* </pre>
*
* Xml Setup (Similar to Java Beans Setup).
*/
@Override
@Before
public void setUp()
{
super.setUp();
spyInstance = getSpyInstance();
final BranchDAO branchDAO = getDaoFacade().getBranchDAO();
final EntryDAO entryDAO = getDaoFacade().getEntryDAO();
testBranch1 = new Branch("RootBranch1", getTestRootBranch());
testBranch1.setBranchId(TEST_ID_RTBRANCH1);
testSubBranch1 = new Branch("SubBranch1", testBranch1);
testSubBranch1.setBranchId(TEST_ID_SUBBRANCH1);
final Entry entry1 = new Entry("Entry Title 1", "Entry Desc 1", testBranch1);
final Entry entry2 = new Entry("Entry Title 2", "Entry Desc 2", testBranch1);
final Entry entry3 = new Entry("Entry Title 3", "Entry Desc 3", testSubBranch1);
when(branchDAO.readAllByParent(Constant.ROOT_ID)).thenReturn(Arrays.asList(new Branch[] { testBranch1 }));
when(branchDAO.readAllByParent(TEST_ID_RTBRANCH1)).thenReturn(Arrays.asList(new Branch[] { testSubBranch1 }));
when(entryDAO.readAllByBranch(TEST_ID_RTBRANCH1)).thenReturn(Arrays.asList(new Entry[] {
entry1,
entry2 }));
when(entryDAO.readAllByBranch(TEST_ID_SUBBRANCH1)).thenReturn(Arrays.asList(new Entry[] { entry3 }));
mockDocument = mock(Document.class);
when(mockDocument.createElement(Mockito.anyString())).thenReturn(mock(Element.class));
final XPathFactory mockXPathFac = mock(XPathFactory.class);
PowerMockito.mockStatic(XPathFactory.class);
when(XPathFactory.newInstance()).thenReturn(mockXPathFac);
when(mockXPathFac.newXPath()).thenReturn(mockXPath);
when(testBranchList1.getLength()).thenReturn(1);
when(testBranchList1.item(0)).thenReturn(testSubBranchEl1);
when(testBranchList2.getLength()).thenReturn(0);
try {
doReturn(testBranch1).when(spyInstance).convertElementToBranch(testBranchEl1, Constant.ROOT_ID);
doReturn(testSubBranch1).when(spyInstance).convertElementToBranch(testSubBranchEl1, TEST_ID_RTBRANCH1);
} catch (final XPathExpressionException e) {
getCommon().failUnexpectedException(e);
}
getLogger().debug("testBranchEl1: " + testBranchEl1.hashCode());
getLogger().debug("testSubBranchEl1: " + testSubBranchEl1.hashCode());
getLogger().debug("testBranchesEl1: " + testBranchesEl1.hashCode());
getLogger().debug("testSubBranchesEl1: " + testSubBranchesEl1.hashCode());
getLogger().debug("testRootBranchEl: " + testRootBranchEl.hashCode());
//when(mockSubBranchList.getLength()).thenReturn(rootBranchCount);
}
/**
* Case 1: Null arguments.
*
* Test method for
* {@link com.philip.journal.home.service.XmlHelper#convertNodeToXml(org.w3c.dom.Document, org.w3c.dom.Element, com.philip.journal.home.bean.Branch)}
* .
*/
@Test(expected = IllegalArgumentException.class)
public final void testConvertNodeToXmlCase1()
{
getTestInstance().convertNodeToXml(null, null, null);
}
/**
* Case 2: Normal flow.
*/
@Test
public final void testConvertNodeToXmlCase2()
{
final String[] branchProperties = BeanUtils.getProperties(testBranch1);
PowerMockito.mockStatic(BeanUtils.class);
when(BeanUtils.getProperties(any(), (String[]) any())).thenReturn(branchProperties);
getTestInstance().convertNodeToXml(mockDocument, testRootBranchEl, getTestRootBranch());
verify(mockDocument, times(TEST_ENTRY_COUNT)).createElement(eq(XmlHelper.TAG_BRANCH));
verify(mockDocument, times(2)).createElement(eq(XmlHelper.TAG_BRANCHES));
verify(mockDocument, times(TEST_ENTRY_COUNT)).createElement(eq(XmlHelper.TAG_ENTRY));
verify(mockDocument, times(2)).createElement(eq(XmlHelper.TAG_ENTRIES));
}
/**
* Test method for
* {@link com.philip.journal.home.service.XmlHelper#attachPropertiesToElement(org.w3c.dom.Document, org.w3c.dom.Element, java.lang.Object)}
* .
*
* Case 1: Null parameters.
*/
@Test(expected = IllegalArgumentException.class)
public final void testAttachPropertiesToElementCase1()
{
getTestInstance().attachPropertiesToElement(null, null, null);
}
/**
* Case 2: Normal flow for Branch.
*/
@Test
public final void testAttachPropertiesToElementCase2()
{
final String[] branchProperties = BeanUtils.getProperties(getTestRootBranch(), XmlHelper.EXCLUDED_PROPS);
PowerMockito.mockStatic(BeanUtils.class);
when(BeanUtils.getProperties(any(), (String[]) any())).thenReturn(branchProperties);
when(BeanUtils.getProperty(eq(getTestRootBranch()), eq(Branch.ATTR_BRANCH_ID))).thenReturn(Constant.ROOT_ID);
when(BeanUtils.getProperty(eq(getTestRootBranch()), eq(Branch.ATTR_NAME))).thenReturn(Constant.ROOT_NAME);
getTestInstance().attachPropertiesToElement(mockDocument, testRootBranchEl, getTestRootBranch());
verify(mockDocument, times(1)).createTextNode(eq(String.valueOf(Constant.ROOT_ID)));
verify(mockDocument, times(1)).createTextNode(eq(Constant.ROOT_NAME));
}
/**
* Case 3: Normal flow for Entry.
*/
@Test
public final void testAttachPropertiesToElementCase3()
{
final Entry entry = new Entry("Entry Title", "Has CDATA <>", getTestRootBranch());
final Element mockRootEl = mock(Element.class);
final String[] entryProperties = BeanUtils.getProperties(entry, XmlHelper.EXCLUDED_PROPS);
PowerMockito.mockStatic(BeanUtils.class);
when(BeanUtils.getProperties(any(), (String[]) any())).thenReturn(entryProperties);
when(BeanUtils.getProperty(entry, Entry.ID)).thenReturn(0);
when(BeanUtils.getProperty(entry, Entry.TITLE)).thenReturn("Entry Title");
when(BeanUtils.getProperty(entry, Entry.DETAIL)).thenReturn("Has CDATA <>");
getTestInstance().attachPropertiesToElement(mockDocument, mockRootEl, entry);
verify(mockDocument, times(1)).createTextNode(eq("Entry Title"));
verify(mockDocument, times(1)).createTextNode(eq(String.valueOf(0)));
verify(mockDocument, times(1)).createCDATASection(eq("Has CDATA <>"));
}
/**
* Case 1: Null parameter.
*
* Test method for
* {@link com.philip.journal.home.service.XmlHelper#extractBranchFromDocument(org.w3c.dom.Element, long)}.
*
* @throws XPathExpressionException For convenience.
*/
@Test(expected = JournalException.class)
public final void testExtractNodeFromDocumentCase1() throws XPathExpressionException
{
getTestInstance().extractBranchFromDocument(null, 0L);
}
/** Case 2: Normal. Too complex!!! */
@Test
public final void testExtractNodeFromDocumentCase2()
{
try {
final BranchDAO branchDAO = getDaoFacade().getBranchDAO();
final int rootBranchCount = branchDAO.readAllByParent(Constant.ROOT_ID).size();
final int branchCount = branchDAO.readAllByParent(TEST_ID_RTBRANCH1).size();
when(mockXPath.evaluate(eq(XmlHelper.TAG_BRANCHES), eq(testBranchEl1), eq(XPathConstants.NODE)))
.thenReturn(testBranchesEl1);
when(mockXPath.evaluate(eq(XmlHelper.TAG_BRANCHES), eq(testSubBranchEl1), eq(XPathConstants.NODE)))
.thenReturn(testSubBranchesEl1);
when(mockXPath.evaluate(eq(XmlHelper.TAG_BRANCH), eq(testBranchesEl1), eq(XPathConstants.NODESET)))
.thenReturn(testBranchList1);
when(mockXPath.evaluate(eq(XmlHelper.TAG_BRANCH), eq(testSubBranchesEl1), eq(XPathConstants.NODESET)))
.thenReturn(testBranchList2);
spyInstance.extractBranchFromDocument(testBranchEl1, Constant.ROOT_ID);
verify(mockXPath, times(1))
.evaluate(eq(XmlHelper.TAG_BRANCHES), eq(testBranchEl1), eq(XPathConstants.NODE));
verify(mockXPath, times(1)).evaluate(eq(XmlHelper.TAG_BRANCHES), eq(testSubBranchEl1),
eq(XPathConstants.NODE));
verify(mockXPath, times(1)).evaluate(eq(XmlHelper.TAG_BRANCH), eq(testBranchesEl1),
eq(XPathConstants.NODESET));
verify(mockXPath, times(1)).evaluate(eq(XmlHelper.TAG_BRANCH), eq(testSubBranchesEl1),
eq(XPathConstants.NODESET));
//Verify Execute once, recurse once.
verify(spyInstance, times(1)).extractBranchFromDocument(eq(testBranchEl1), eq(1L));
verify(spyInstance, times(branchCount)).extractBranchFromDocument(eq(testSubBranchEl1),
Matchers.eq(TEST_ID_RTBRANCH1));
verify(spyInstance, times(rootBranchCount)).extractEntryFromDocument(eq(testBranchEl1), eq(testBranch1));
verify(spyInstance, times(branchCount)).extractEntryFromDocument(eq(testSubBranchEl1), eq(testSubBranch1));
} catch (final XPathExpressionException ex) {
getCommon().failUnexpectedException(ex);
}
}
/**
* Case 1: Null first parameter.<br/>
*
* Test method for
* {@link com.philip.journal.home.service.XmlHelper#convertElementToBranch(org.w3c.dom.Element, long)}.
*
* @throws XPathExpressionException For convenience.
*/
@Test(expected = JournalException.class)
public final void testConvertElementToBranchCase1() throws XPathExpressionException
{
getTestInstance().convertElementToBranch(null, 1L);
}
/**
* Case 2: Invalid parent ID.
*
* @throws XPathExpressionException For convenience.
*/
@Test(expected = JournalException.class)
public final void testConvertElementToBranchCase2() throws XPathExpressionException
{
getTestInstance().convertElementToBranch(testBranchEl1, TEST_BOGUS_ID);
}
/**
* Case 1: Null argument. Test method for
*
* {@link com.philip.journal.home.service.XmlHelper#getElementPropValue(org.w3c.dom.Element, java.lang.Class, java.lang.String)}
* .
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase1() throws XPathExpressionException
{
getTestInstance().getElementPropValue(null, null, null);
}
/**
* Case 2: Long type.
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase2() throws XPathExpressionException
{
when(mockXPath.evaluate("branchId", testRootBranchEl, XPathConstants.STRING)).thenReturn(
String.valueOf(Constant.ROOT_ID));
assertEquals("Case 2: Long type.", Constant.ROOT_ID,
getTestInstance().getElementPropValue(testRootBranchEl, Long.TYPE, "branchId"));
}
/**
* Case 3: String type.
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase3() throws XPathExpressionException
{
when(mockXPath.evaluate("name", testRootBranchEl, XPathConstants.STRING)).thenReturn(Constant.ROOT_NAME);
assertEquals("Case 3: String type.", Constant.ROOT_NAME,
getTestInstance().getElementPropValue(testRootBranchEl, String.class, "name"));
}
/**
* Case 4: Invalid Time.
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase4() throws XPathExpressionException
{
when(mockXPath.evaluate(AbstractAuditableBean.CREATE_TIME, testRootBranchEl, XPathConstants.STRING))
.thenReturn("invalid");
assertNull("Case 4: Invalid Time.",
getTestInstance().getElementPropValue(testRootBranchEl, Date.class, AbstractAuditableBean.CREATE_TIME));
}
/**
* Case 5: Invalid Date.
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase5() throws XPathExpressionException
{
when(mockXPath.evaluate(AbstractAuditableBean.CREATE_DATE, testRootBranchEl, XPathConstants.STRING))
.thenReturn("invalid");
assertNull("Case 5: Invalid Date.",
getTestInstance().getElementPropValue(testRootBranchEl, Date.class, AbstractAuditableBean.CREATE_DATE));
}
/**
* Case 6: Unsupported Type.
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase6() throws XPathExpressionException
{
when(mockXPath.evaluate(AbstractAuditableBean.CREATE_DATE, testRootBranchEl, XPathConstants.STRING))
.thenReturn(1);
assertNull("Case 6: Unsupported Type.",
getTestInstance().getElementPropValue(testRootBranchEl, Integer.class, Branch.ATTR_BRANCH_ID));
}
/**
* Case 7: User type.
*
* @throws XPathExpressionException for convenience.
*/
@Test
public final void testGetElementPropValueCase7() throws XPathExpressionException
{
when(mockXPath.evaluate(AbstractAuditableBean.CREATOR, testRootBranchEl, XPathConstants.STRING)).thenReturn(
JournalTestCommon.TEST_USERNAME);
final User user = mock(User.class);
when(getDaoFacade().getUserDAO().readByUsername(Mockito.eq(JournalTestCommon.TEST_USERNAME))).thenReturn(user);
assertEquals("Case 7: User type.", user,
getTestInstance().getElementPropValue(testRootBranchEl, User.class, AbstractAuditableBean.CREATOR));
}
/*
* (non-Javadoc)
* @see com.philip.journal.core.service.AbstractPowerMockJournalTestService#getTestInstanceClass()
*/
@Override
protected Class<XmlHelper> getTestInstanceClass()
{
return XmlHelper.class;
}
}