2014-09-03 12 views
5

Ho intenzione di creare un XML da una stringa. SembraCome generare un ParserConfigurationException durante la creazione di un nuovo file xml tramite DocumentBuidlerFactory

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 

public Document createCompleteExportXml(String xmlFilename, String content) { 
    try { 
     DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder(); 

     //create the XML file here 
    } catch (ParserConfigurationException pce) { 
     LOGGER.trace("parsing error ", pce); 
    } 
} 

Ora devo verificare se l'eccezione può essere catturata in un test di Junit.

@Test(expected=ParserConfigurationException.class) 
public void createCompleteExportXmlWithParseConfigurationException() { 
    String xmlFilename = "junitExportTestWithParseConfigurationException.xml"; 
    String content = "any content"; 
    XmlFileWriter writer = new XmlFileWriter(); 
    Document doc = writer.createCompleteExportXml(xmlFilename, content); 
} 

Come posso fare questo test lanciare il ParserConfigurationException?

Rendo la mia domanda più concreta: come posso rendere documentFactory.newDocumentBuilder() non in grado di funzionare, perché "non è possibile creare un DocumentBuilder che soddisfi la configurazione richiesta."? Dov'è la configurazione? Come posso cambiarlo intenzionalmente in uno sbagliato?

+0

Quale classe concreta è il 'documentFacory'? – Jens

+0

Non lo so. Ho appena importato i pacchetti e funzionano. Come posso vedere quale classe concreta viene utilizzata? – user3778446

+0

Prova ad aggiungere 'System.out.println (documentFactory.getClass(). GetName())'. Quindi dovresti ottenere il nome della classe concreato o usare il debugger. Questo ti mostrerà il nome della classe. – Jens

risposta

2

Il tuo test non sta passando perché stai prendendo precisamente il codice ParserConfigurationException nel tuo metodo, quindi non viene mai lanciato. Per superare il test:

1) modificare la firma del metodo (gettando eccezione)

public String createCompleteExportXml(String xmlFilename, String content) throws ParserConfigurationException { 

2) Lanciate il ParserConfigurationException. Per fare ciò, è possibile rimuovere il blocco catch o lanciare l'eccezione dopo LOGGER.trace. Esempio per la seconda opzione:

try { 
    //... 
    } catch (ParserConfigurationException pce) { 
    LOGGER.trace("parsing error ", pce); 
    throw pce; 
    } 

Spero che ti aiuta

[UPDATE]

Se si vuole simulare un ParserConfigurationException, è possibile utilizzare un framework come Mockito/PowerMock per deridere DocumentBuilderFactory e simulare che ParserConfigurationException viene generato quando viene chiamato il metodo newDocumentBuilder().

Esempio:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(DocumentBuilderFactory.class) 
public class XmlFileWriterTest { 

    @Test(expected = ParserConfigurationException.class) 
    public void createCompleteExportXmlWithParseConfigurationException() throws Exception { 
     String xmlFilename = "junitExportTestWithParseConfigurationException.xml"; 
     String content = "any content"; 
     XmlFileWriter writer = new XmlFileWriter(); 

     // Mock DocumentBuilderFactory: When method newDocumentBuilder() is called, throws a simulated ParserConfigurationException 
     DocumentBuilderFactory mockDocumentBuilderFactory = PowerMockito.mock(DocumentBuilderFactory.class); 
     PowerMockito.when(mockDocumentBuilderFactory.newDocumentBuilder()).thenThrow(new ParserConfigurationException("Simulated ex")); 

     // Mock DocumentBuilderFactory.newInstance(), when is called, returns your mock instance mockDocumentBuilderFactory 
     PowerMockito.mockStatic(DocumentBuilderFactory.class); 
     PowerMockito.when(DocumentBuilderFactory.newInstance()).thenReturn(mockDocumentBuilderFactory); 

     writer.createCompleteExportXml(xmlFilename, content); 
    } 

Questo passaggio di prova (con suggerimenti codice precedenti fatto).

dipendenze Maven per powerMock:

<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-module-junit4</artifactId> 
    <version>1.5.4</version> 
    </dependency> 

    <dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-api-mockito</artifactId> 
    <version>1.5.4</version> 
    </dependency> 

Spero che questo sarebbe quello che state cercando.

Potete trovare maggiori documentazione Mockito e PowerMock

+2

Grazie. Ho intenzione di modificare il mio codice in base al tuo suggerimento. Ma in via definitiva sto chiedendo come posso simulare un errore ParserConfigurationException. Come posso rendere documentFactory.newDocumentBuilder() non in grado di funzionare, perché "non è possibile creare un DocumentBuilder che soddisfi la configurazione richiesta."? Dov'è la configurazione? Come posso cambiarlo? – user3778446

+1

Ciao, dai un'occhiata al mio aggiornamento della risposta. È possibile utilizzare un framework di simulazione come Mockito/PowerMock per simulare ParserConfigurationException. Spero che ti aiuti. – troig

+0

L'esempio è così buono, avevo quasi bisogno di copiare e incollare, ma quando ho fatto clic con il tasto destro del mouse sulla classe ed eseguito come test di junit. Ho ricevuto: messaggio lì (vedi la mia edizione dopo il codice) – user3778446

3

Come si può vedere nella source code:

public DocumentBuilder newDocumentBuilder() 
    throws ParserConfigurationException 
{   
    // Check that if a Schema has been specified that neither of the schema properties have been set. 

    if (grammar != null && attributes != null) { 
     if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_LANGUAGE)) { 
      throw new ParserConfigurationException(
        SAXMessageFormatter.formatMessage(null, 
        "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_LANGUAGE})); 
     } 
     else if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_SOURCE)) { 
      throw new ParserConfigurationException(
        SAXMessageFormatter.formatMessage(null, 
        "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_SOURCE})); 
     } 
    } 



    try { 

     return new DocumentBuilderImpl(this, attributes, features, fSecureProcess); 
    } catch (SAXException se) { 
     // Handles both SAXNotSupportedException, SAXNotRecognizedException 
     throw new ParserConfigurationException(se.getMessage()); 
    } 
} 

se lo schema è definito il doppio del ParserConfigurationException è gettato per esempio

+1

Sì, ma dove posso definire lo schema due volte nel mio test? – user3778446

1

I don Penso che una delle risposte esistenti abbia davvero risposto alla domanda, quindi ecco la mia opinione su questo.

Avvicinarsi a uno, approfittando di com.sun.* interni parser:.

(classe Helper)

import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.validation.Schema; 
import javax.xml.validation.Validator; 
import javax.xml.validation.ValidatorHandler; 

public class MisconfiguredDocumentBuilderFactory extends DocumentBuilderFactoryImpl { 
    @Override 
    public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { 

     super.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", 
      "http://www.w3.org/2001/XMLSchema"); 
     super.setSchema(new Schema() { 
      @Override 
      public Validator newValidator() { 
       return null; 
      } 

      @Override 
      public ValidatorHandler newValidatorHandler() { 
       return null; 
      } 
     }); 
     return super.newDocumentBuilder(); 
    } 
} 

(Actual classe di test)

public class OPClassTest { 
    private final static String DOC_BUILDER_PROPERTY_NAME = 
     "javax.xml.parsers.DocumentBuilderFactory"; 

    @Test 
    public void testParserConfigurationProblem() { 
     System.setProperty(DOC_BUILDER_PROPERTY_NAME, 
      MisconfiguredDocumentBuilderFactory.class.getCanonicalName()); 
     targetClass.createCompleteExportXml("somefilename", "somecontent"); 
    } 
    @After 
    public void tearDown() { 
     System.clearProperty(DOC_BUILDER_PROPERTY_NAME); 
    } 
} 

Approach 2, senza l'utilizzo di com.sun * namespace

(classe Helper)

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 

public class MisconfiguredDocumentBuilderFactory2 extends DocumentBuilderFactory { 
    @Override 
    public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { 

     throw new ParserConfigurationException(
      "this factory is not configured properly"); 
    } 

    @Override 
    public void setAttribute(String name, Object value) throws IllegalArgumentException { 
     // no-op 
    } 

    @Override 
    public Object getAttribute(String name) throws IllegalArgumentException { 
     return null; 
    } 

    @Override 
    public void setFeature(String name, boolean value) throws ParserConfigurationException { 
     // no-op 
    } 

    @Override 
    public boolean getFeature(String name) throws ParserConfigurationException { 
     return false; 
    } 
} 

(Classe di prova effettiva)

public class OPClassTest { 
    private final static String DOC_BUILDER_PROPERTY_NAME = 
     "javax.xml.parsers.DocumentBuilderFactory"; 

    @Test 
    public void testParserConfigurationProblem() { 
     System.setProperty(DOC_BUILDER_PROPERTY_NAME, 
      MisconfiguredDocumentBuilderFactory2.class.getCanonicalName()); 
     targetClass.createCompleteExportXml("somefilename", "somecontent"); 
    } 
    @After 
    public void tearDown() { 
     System.clearProperty(DOC_BUILDER_PROPERTY_NAME); 
    } 
} 
Problemi correlati