/*
* This program is part of the OpenLMIS logistics management information system platform software.
* Copyright © 2013 VillageReach
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses. For additional information contact info@OpenLMIS.org.
*/
package org.openlmis.shipment.file;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.openlmis.core.domain.EDIConfiguration;
import org.openlmis.core.domain.EDIFileColumn;
import org.openlmis.core.domain.EDIFileTemplate;
import org.openlmis.db.categories.UnitTests;
import org.openlmis.order.domain.Order;
import org.openlmis.order.service.OrderService;
import org.openlmis.shipment.ShipmentLineItemTransformer;
import org.openlmis.shipment.domain.ShipmentLineItem;
import org.openlmis.shipment.dto.ShipmentLineItemDTO;
import org.openlmis.shipment.handler.ShipmentFilePostProcessHandler;
import org.openlmis.shipment.handler.ShipmentFileProcessor;
import org.openlmis.shipment.service.ShipmentFileTemplateService;
import org.openlmis.shipment.service.ShipmentService;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.supercsv.io.CsvListReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static com.natpryce.makeiteasy.MakeItEasy.*;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import static org.openlmis.shipment.builder.ShipmentFileColumnBuilder.*;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.whenNew;
import static org.supercsv.prefs.CsvPreference.STANDARD_PREFERENCE;
@Category(UnitTests.class)
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(BlockJUnit4ClassRunner.class)
@PrepareForTest({ShipmentFileProcessor.class, MessageBuilder.class})
public class ShipmentFileProcessorTest {
@Mock
private ShipmentFilePostProcessHandler shipmentFilePostProcessHandler;
@Mock
ShipmentFileTemplateService shipmentFileTemplateService;
@Mock
ShipmentService shipmentService;
@Mock
Message message;
@Mock
File shipmentFile;
@Mock
FileInputStream shipmentInputStream;
@Mock
ShipmentLineItemTransformer shipmentLineItemTransformer;
@Mock
FileReader mockedFileReader;
@Mock
CsvListReader mockedCsvListReader;
@Mock
private OrderService orderService;
@Mock
ApplicationContext applicationContext;
@InjectMocks
private ShipmentFileProcessor shipmentFileProcessor;
EDIConfiguration shipmentConfiguration;
Date creationDate;
@Before
public void setUp() throws Exception {
when(message.getPayload()).thenReturn(shipmentFile);
whenNew(FileInputStream.class).withArguments(shipmentFile).thenReturn(shipmentInputStream);
whenNew(FileReader.class).withArguments(shipmentFile).thenReturn(mockedFileReader);
whenNew(CsvListReader.class).withArguments(mockedFileReader, STANDARD_PREFERENCE).thenReturn(mockedCsvListReader);
mockStatic(Paths.class);
Path path = mock(Path.class);
String shipmentFilePath = "testPath";
when(shipmentFile.getPath()).thenReturn(shipmentFilePath);
when(Paths.get(shipmentFilePath)).thenReturn(path);
mockStatic(Files.class);
BasicFileAttributes attributes = mock(BasicFileAttributes.class);
when(Files.readAttributes(path, BasicFileAttributes.class)).thenReturn(attributes);
FileTime fileTime = FileTime.from(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
when(attributes.creationTime()).thenReturn(fileTime);
creationDate = new Date();
whenNew(Date.class).withArguments(fileTime.toMillis()).thenReturn(creationDate);
shipmentConfiguration = new EDIConfiguration(false);
}
@Test
public void shouldThrowErrorIfNotEnoughFieldsInShipmentFile() throws Exception {
List<EDIFileColumn> shipmentFileColumnList = new ArrayList<>();
shipmentFileColumnList.add(make(a(mandatoryShipmentFileColumn, with(columnPosition, 1))));
shipmentFileColumnList.add(make(a(mandatoryShipmentFileColumn, with(columnPosition, 2))));
shipmentFileColumnList.add(make(a(mandatoryShipmentFileColumn, with(columnPosition, 3))));
EDIFileTemplate shipmentFileTemplate = new EDIFileTemplate(shipmentConfiguration, shipmentFileColumnList);
when(shipmentFileTemplateService.get()).thenReturn(shipmentFileTemplate);
when(mockedCsvListReader.read()).thenReturn(asList("field1", "field2")).thenReturn(null);
try {
shipmentFileProcessor.process(message);
} catch (Exception e) {
assertThat(e.getMessage(), is("shipment.file.error"));
}
verify(shipmentService, times(0)).save(any(ShipmentLineItem.class));
verify(shipmentFilePostProcessHandler).process(new HashSet<String>(), shipmentFile, false);
}
@Test
public void shouldInsertLineItemsIfAllIncludedFieldsArePresent() throws Exception {
List<EDIFileColumn> shipmentFileColumnList = new ArrayList<EDIFileColumn>() {{
add(make(a(mandatoryShipmentFileColumn, with(fieldName, "orderNumber"), with(columnPosition, 2))));
add(make(a(defaultShipmentFileColumn, with(columnPosition, 4), with(includeInShipmentFile, false))));
add(make(a(defaultShipmentFileColumn, with(columnPosition, 6), with(includeInShipmentFile, false))));
}};
EDIFileTemplate shipmentFileTemplate = new EDIFileTemplate(shipmentConfiguration, shipmentFileColumnList);
when(shipmentFileTemplateService.get()).thenReturn(shipmentFileTemplate);
when(mockedCsvListReader.read()).thenReturn(asList("", "OYELL_FVR00000123R")).thenReturn(null);
ShipmentLineItem lineItem = new ShipmentLineItem();
when(shipmentLineItemTransformer.transform(any(ShipmentLineItemDTO.class), anyString(), anyString(), any(Date.class))).thenReturn(lineItem);
when(applicationContext.getBean(ShipmentFileProcessor.class)).thenReturn(shipmentFileProcessor);
when(orderService.isShippable("OYELL_FVR00000123R")).thenReturn(true);
Order order = new Order(123L);
when(orderService.getByOrderNumber("OYELL_FVR00000123R")).thenReturn(order);
shipmentFileProcessor.process(message);
verify(mockedCsvListReader, times(0)).getHeader(true);
verify(shipmentService, times(1)).save(any(ShipmentLineItem.class));
Set<String> orderNumbers = new HashSet<>();
orderNumbers.add("OYELL_FVR00000123R");
verify(shipmentFilePostProcessHandler).process(orderNumbers, shipmentFile, true);
}
@Test
public void shouldRemoveHeadersIfPresentInCsv() throws Exception {
List<EDIFileColumn> shipmentFileColumnList = new ArrayList<EDIFileColumn>() {{
add(make(a(mandatoryShipmentFileColumn, with(columnPosition, 2))));
}};
boolean headerInFile = true;
EDIFileTemplate shipmentFileTemplate = new EDIFileTemplate(new EDIConfiguration(headerInFile), shipmentFileColumnList);
when(shipmentFileTemplateService.get()).thenReturn(shipmentFileTemplate);
when(applicationContext.getBean(ShipmentFileProcessor.class)).thenReturn(shipmentFileProcessor);
when(mockedCsvListReader.read()).thenReturn(null);
shipmentFileProcessor.process(message);
verify(mockedCsvListReader).getHeader(true);
verify(shipmentFilePostProcessHandler).process(new HashSet<String>(), shipmentFile, false);
}
@Test
public void shouldCreateDTOIfDateFieldsArePresent() throws Exception {
List<EDIFileColumn> shipmentFileColumnList = new ArrayList<EDIFileColumn>() {{
add(make(a(mandatoryShipmentFileColumn,
with(columnPosition, 1),
with(fieldName, "orderNumber")
)));
add(make(a(mandatoryShipmentFileColumn,
with(columnPosition, 2),
with(fieldName, "packedDate"),
with(dateFormat, "MM/yy")
)));
add(make(a(defaultShipmentFileColumn,
with(columnPosition, 3),
with(fieldName, "shippedDate"),
with(dateFormat, "dd/MM/yyyy")
)));
}};
EDIFileTemplate shipmentFileTemplate = new EDIFileTemplate(shipmentConfiguration, shipmentFileColumnList);
when(shipmentFileTemplateService.get()).thenReturn(shipmentFileTemplate);
when(mockedCsvListReader.read()).thenReturn(asList("OYELL_FVR00000123R", "11/13", "11/11/2011")).thenReturn(null);
ShipmentLineItemDTO shipmentLineItemDTO = new ShipmentLineItemDTO();
shipmentLineItemDTO.setOrderNumber("OYELL_FVR00000123R");
shipmentLineItemDTO.setPackedDate("11/13");
shipmentLineItemDTO.setShippedDate("11/11/2011");
shipmentLineItemDTO.setOrderId(123L);
ShipmentLineItem shipmentLineItem = mock(ShipmentLineItem.class);
when(orderService.isShippable("OYELL_FVR00000123R")).thenReturn(true);
when(shipmentLineItemTransformer.transform(shipmentLineItemDTO, "MM/yy", "dd/MM/yyyy", creationDate)).thenReturn(shipmentLineItem);
when(applicationContext.getBean(ShipmentFileProcessor.class)).thenReturn(shipmentFileProcessor);
Order order = new Order(123L);
when(orderService.getByOrderNumber("OYELL_FVR00000123R")).thenReturn(order);
shipmentFileProcessor.process(message);
verify(shipmentService).save(shipmentLineItem);
HashSet<String> orderNumbers = new HashSet<>();
orderNumbers.add("OYELL_FVR00000123R");
verify(shipmentFilePostProcessHandler).process(orderNumbers, shipmentFile, true);
}
}