Как проверить метод void, используя JUnit и / или Mockito - PullRequest
0 голосов
/ 05 ноября 2018

Заранее извиняюсь - я знаю, что об этом просили тысячу раз, но я просмотрел очень много статей / документации, и я просто так потерян.

У меня есть класс, который принимает XML-файл, а затем использует DocumentBuilder для анализа его в новый файл, который будет использоваться в качестве источника для других классов.

Мне нужно проверить мой метод (который является недействительным). Мой проект завершен, но мне нужно проверить.

Если кто-то может так любезно показать мне, как это будет сделано, я могу пойти дальше и следовать той же логике с другими моими классами, поскольку 90% методов в моем проекте ничего не возвращают.

Спасибо ...

 public class XmlToCsv {


    public static void xmlToCsv(String sourceXlsFile, String sourceCsvFile, String sourceXmlFile) throws Exception {

        //define the files
        File stylesheet = new File(sourceXlsFile);
        File xmlSource = new File(sourceXmlFile);

        //create the DocumentBuilder to parse the XML file
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(xmlSource);

        //input the stylesheet to transform the XML to
        StreamSource stylesource = new StreamSource(stylesheet);
        Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);

        //write a new output file using the stylesheet format
        Source source = new DOMSource(document);
        Result outputTarget = new StreamResult(new File(sourceCsvFile));
        transformer.transform(source, outputTarget);

    }
}

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

То, что вы пытаетесь сделать, на самом деле не способ сделать это. Вы должны проверять ТОЛЬКО класс XmlToCsv, а не классы, используемые этим классом (DocumentBuilderFactory, DocumentBuilder, Document, StreamSource, Transformer, Source, Result).

Теперь есть 2 способа: чистый код или грязный тест.

Лучшее решение - у вас есть структура зависимостей для используемых вами классов:

public class XmlToCsv {

    @Inject
    DocumentBuilderFactory factory;

    @Inject
    StreamSource stylesource;

    @Inject
    TransformerFactory transformerFactory;

    public void xmlToCsv(String sourceXlsFile, String sourceCsvFile, String sourceXmlFile) throws Exception {

        //define the files
        File stylesheet = new File(sourceXlsFile);
        File xmlSource = new File(sourceXmlFile);

        //create the DocumentBuilder to parse the XML file
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(xmlSource);

        //input the stylesheet to transform the XML to
        StreamSource stylesource = new StreamSource(stylesheet);
        Transformer transformer = transformerFactory.newInstance().newTransformer(stylesource);

        //write a new output file using the stylesheet format
        Source source = new DOMSource(document);
        Result outputTarget = new StreamResult(new File(sourceCsvFile));
        transformer.transform(source, outputTarget);

    }
}

Теперь тестирование можно выполнить, введя макеты в поля ввода:

@RunWith(MockitoJUnitRunner.class)
public class XmlToCsvTest {
    @Mock
    DocumentBuilderFactory factory;

    @Mock
    StreamSource style source;

    @Mock
    TransformerFactory transformerFactory;

    @InjectMocks
    XmlToCsv sut; // System Under Test

    @Test
    public void testOk() throws Exception {
        // Mocks
        DocumentBuilder documentBuilder = Mockito.mock(DocumentBuilder.class);
        Document document = Mockito.mock(Document.class);
        // Now you control all objects created in the class and you can test if the right methods are called

        // when-clauses
        Mockito.when(factory.newDocumentBuilder).thenReturn(documentBuilder);
        Mockito.when(documentBuilder.parse(any(File.class)).thenReturn(document);
        // Add all when's here

        // now call the class
        sut.xmlToCsv("", "", "");

        // now verify all calls
        verify(factory, times(1)).newDocumentBuilder();
        verify(documentBuilder, times(1)).parse(any(File.class));
        // etc.
    }
}

Грязный путь - использование PowerMockito. С PowerMockito вы можете переопределить новые методы существующих классов. Это действительно последнее средство, и я бы не стал его рекомендовать, но вы можете использовать его, когда не можете изменить исходный код. Это будет выглядеть примерно так:

@RunWith(PowerMockRunner.class)
@PrepareForTest({XmlToCsv.class, DocumentBuilderFactory.class})
public class XmlToCsvTest {

    XmlToCsv sut;

    @Test
    public void testXmlToCsv() throws Exception {
        DocumentBuilder documentBuilder = Mockito.mock(DocumentBuilder.class);
        Document document = Mockito.mock(Document.class);

        //when phase
        PowerMockito.mockStatic(DocumentBuilderFactory.newInstance).thenReturn(documentBuilder);
        Mockito.when(factory.newDocumentBuilder).thenReturn(documentBuilder);
        Mockito.when(documentBuilder.parse(any(File.class)).thenReturn(document);

        // now call the class
        sut.xmlToCsv("", "", "");

        //now verify

verify(documentBuilder, times(1)).parse(any(File.class));
    }
}

Как видите, примеры не завершены, но вы понимаете разницу.

0 голосов
/ 07 ноября 2018

Чтобы проверить генератор кода, это лучший подход, который я нашел:

  1. Подготовьте набор тестовых случаев с одинаковым XSL: для каждого входной файл XML и ожидаемый выходной файл CSV. Поместите входные файлы в каталог, а ожидаемые - в другой, но задайте одинаковые имена для каждой пары файлов (case1.xml и case1.csv).

  2. Код JUnit-класса с закрытым методом, который должен выполнять тестирование и сравнение, а затем добавьте один @Test метод для каждого случая, который вы хотите проверить:

    import java.io.File;
    import org.apache.commons.io.FileUtils;
    
    public class XmlToCsvTest
    {
      private final File inputDir=new File("my_input_xml_files");
    
      private final File expectedDir=new File("my_expected_csv_files");
    
      private final File generatedDir=new File("my_generated_files"); // This is just a working dir
    
      private void xmlToCsv(String xslFile, String inputFileName)
      {
        try
        {
          File inputXmlFile=new File(this.inputDir, inputFileName + ".xml");
          File outputCsvFile=new File(this.generatedDir, inputFileName + ".csv");
          File expectedCsvFile=new File(this.expectedDir, inputFileName + ".csv");
          xmlToCsv(xslFile, outputCsvFile.getAbsolutePath(), inputXmlFile.getAbsolutePath());
          FileUtils.contentEquals(expectedCsvFile, outputCsvFile);
        }
        catch (Exception e)
        {
          fail(e.toString());
        }
      }
    
      @Test
      public void xmlToCsvWithCase1()
      {
        xmlToCsv("myFirst.xsl", "case1");
      }
    
      @Test
      public void xmlToCsvWithEmptyFile()
      {
        xmlToCsv("myFirst.xsl", "empty");
      }
    
      @Test
      public void xmlToCsvWithOneRow()
      {
        xmlToCsv("myFirst.xsl", "one-row");
      }
    
        ...
    }
    
  3. Как только вы освоите эту технику, вы можете добавить больше сложности своим тестам, добавив другие XSL с собственными тестовыми примерами.

Не забудьте добавить набор файлов в ваш проект в качестве ресурсов, чтобы стать частью системы контроля версий.

Примечание. Этот подход предполагает, что каждый выходной файл зависит только от содержимого входного файла. Если генератор добавляет какой-либо независимый контент (например, текущая дата, текущий пользователь и т. Д.), Необходимо выполнить предварительную предварительную обработку.

0 голосов
/ 05 ноября 2018

Похоже, что вы хотите проверить этот метод, чтобы проверить ожидаемое содержимое файла, записанного в аргумент sourceCsvFile, что вы можете сделать, прочитав содержимое после вызова вашего метода. Я не думаю, что вам нужно что-то делать с Mockito - все ваши аргументы являются объектами String, и поэтому нет необходимости создавать какие-либо насмешки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...