434 lines
17 KiB
C#
434 lines
17 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Moq;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using TechTalk.SpecFlow;
|
|
using TechTalk.SpecFlow.Assist;
|
|
using TechTalk.SpecFlow.Assist.ValueRetrievers;
|
|
using Xunit;
|
|
using ReserveManagementSystemApi.ServiceClients;
|
|
using ReserveManagementSystemApi.Services;
|
|
using ReserveManagementSystemLib.Configuration;
|
|
using ReserveManagementSystemLib.Models;
|
|
using ReserveManagementSystemLib.Persistence;
|
|
using ReserveManagementSystemLib.Repositories;
|
|
using LCU.Library.Internal.ApiSecurity.Enums;
|
|
using LCU.Library.Internal.ApiSecurity.Models;
|
|
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.IndirectLoan;
|
|
using LCU.Library.Internal.LcuHttpClient.HttpRequest;
|
|
|
|
namespace ReserveManagementSystemApi.Tests.Features
|
|
{
|
|
[Binding]
|
|
public sealed class ImportReadServiceSteps
|
|
{
|
|
// For additional details on SpecFlow step definitions see https://go.specflow.org/doc-stepdef
|
|
|
|
private readonly ScenarioContext _scenarioContext;
|
|
private ApiSecurityConfiguration _apiSecurityConfiguration;
|
|
private ImportReadService _importReadService;
|
|
private LoanRepository _loanRepository;
|
|
private LoanTypeRepository _loanTypeRepository;
|
|
private DealerRepository _dealerRepository;
|
|
private DealerService _dealerService;
|
|
private Mock<IAuditHistoryRepository> _mockAuditHistRepo;
|
|
private Mock<IExportService> _mockExportService;
|
|
private LoanService _loanService;
|
|
private ImportRepository _importRepository;
|
|
private ImportService _importService;
|
|
private AppDbContext _appDbContext;
|
|
private Import _importResult;
|
|
private Exception _exception;
|
|
private string _importFileName;
|
|
private StreamReader _importStreamReader;
|
|
private List<Loan> _loansResult;
|
|
private List<Dealer> _dealersResult;
|
|
private List<IndirectLoanDetail> _loanDetailsFromDNA;
|
|
private List<ClosedIndirectLoan> _closedLoansFromDNA;
|
|
private Mock<CoreApiConfiguration> _mockCoreApiConfiguration;
|
|
private Mock<IGetRequest> _mockgetRequest;
|
|
private Mock<IPostRequest> _mockpostRequest;
|
|
private Mock<IPutRequest> _mockputRequest;
|
|
|
|
public ImportReadServiceSteps(ScenarioContext scenarioContext)
|
|
{
|
|
_scenarioContext = scenarioContext;
|
|
Service.Instance.ValueRetrievers.Register(new NullValueRetriever("<null>"));
|
|
}
|
|
|
|
[BeforeScenario]
|
|
public void CreateDatabase()
|
|
{
|
|
var options = new DbContextOptionsBuilder<AppDbContext>()
|
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
|
.Options;
|
|
_apiSecurityConfiguration = new ApiSecurityConfiguration(ApiKeyAuthenticationFailureBehavior.Warn);
|
|
_mockCoreApiConfiguration = new Mock<CoreApiConfiguration>();
|
|
_mockCoreApiConfiguration.Object.ApiTimeOutInSeconds = "420";
|
|
_mockpostRequest = new Mock<IPostRequest>();
|
|
_mockputRequest = new Mock<IPutRequest>();
|
|
_mockgetRequest = new Mock<IGetRequest>();
|
|
_appDbContext = new AppDbContext(options);
|
|
_loanRepository = new LoanRepository(_appDbContext);
|
|
_loanTypeRepository = new LoanTypeRepository(_appDbContext);
|
|
_dealerRepository = new DealerRepository(_appDbContext);
|
|
_importRepository = new ImportRepository(_appDbContext);
|
|
_mockAuditHistRepo = new Mock<IAuditHistoryRepository>();
|
|
_mockExportService = new Mock<IExportService>();
|
|
_dealerService = new DealerService(_dealerRepository);
|
|
_loanService = new LoanService(_loanRepository, _loanTypeRepository, new AuditHistoryService(_mockAuditHistRepo.Object),
|
|
new Mock<ICoreApiServiceClient>().Object);
|
|
_importService = new ImportService(_importRepository);
|
|
_importReadService = new ImportReadService(
|
|
_loanService, _importService,
|
|
_dealerService,
|
|
_mockExportService.Object,
|
|
new CoreApiServiceClient(_apiSecurityConfiguration, _mockCoreApiConfiguration.Object, _mockgetRequest.Object, _mockpostRequest.Object, _mockputRequest.Object),
|
|
new Mock<RmsApiConfiguration>().Object
|
|
);
|
|
}
|
|
|
|
[AfterScenario]
|
|
public void DisposeAppDbContext()
|
|
{
|
|
_appDbContext.Database.EnsureDeleted();
|
|
_appDbContext.Dispose();
|
|
}
|
|
|
|
[Given(@"an import file named ""(.*)"" that contains")]
|
|
public void GivenAnImportFileNamedThatContains(string fileName, string fileContent)
|
|
{
|
|
_importFileName = fileName;
|
|
var byteArray = Encoding.UTF8.GetBytes(fileContent);
|
|
var stream = new MemoryStream(byteArray);
|
|
_importStreamReader = new StreamReader(stream);
|
|
}
|
|
|
|
[Given(@"that I get these closed loans back from DNA")]
|
|
public void GivenThatIGetTheseClosedLoansBackFromDNA(Table table)
|
|
{
|
|
_closedLoansFromDNA = table.CreateSet<ClosedIndirectLoan>().ToList();
|
|
}
|
|
|
|
[Given(@"an import from DNA that contains")]
|
|
public void GivenAnImportFromDNAThatContains(Table table)
|
|
{
|
|
_loanDetailsFromDNA = table.CreateSet<IndirectLoanDetail>().ToList();
|
|
}
|
|
|
|
[Given(@"a loan table consisting of")]
|
|
public void GivenALoanTableConsistingOf(Table table)
|
|
{
|
|
var loans = table.CreateSet<Loan>().ToList();
|
|
_appDbContext.Loans.AddRange(loans);
|
|
_appDbContext.SaveChanges();
|
|
}
|
|
|
|
[Given(@"a loan type table consisting of")]
|
|
public void GivenALoanTypeTableConsistingOf(Table table)
|
|
{
|
|
var types = table.CreateSet<LoanType>().ToList();
|
|
_appDbContext.LoanTypes.AddRange(types);
|
|
_appDbContext.SaveChanges();
|
|
}
|
|
|
|
[Given(@"dealers that look like")]
|
|
public void GivenDealersThatLookLike(Table table)
|
|
{
|
|
var dealers = table.CreateSet<Dealer>().ToList();
|
|
_appDbContext.Dealers.AddRange(dealers);
|
|
_appDbContext.SaveChanges();
|
|
}
|
|
|
|
[Given(@"the current vehicle for loanId (.*) is")]
|
|
public void GivenTheCurrentVehicleForLoanIdIs(int loanId, Table table)
|
|
{
|
|
var vehicle = table.CreateInstance<Vehicle>();
|
|
vehicle.LoanId = loanId;
|
|
_appDbContext.Vehicles.Add(vehicle);
|
|
_appDbContext.SaveChanges();
|
|
}
|
|
|
|
[When(@"I read this new loan import file at ""(.*)""")]
|
|
public async void WhenIReadThisNewLoanImportFileAt(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ReadNewLoanImportFile(_importStreamReader, _importFileName, currentTime);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process this DNA new/updated loan import at ""(.*)""")]
|
|
public async void WhenIReadThisNewDNALoanImportFileAt(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ProcessActiveLoanImport(_loanDetailsFromDNA, currentTime);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process this DNA new/updated loan import at ""(.*)"" and skip the export")]
|
|
public async void WhenIProcessThisDNANewUpdatedLoanImportAtAndSkipTheExport(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ProcessActiveLoanImport(_loanDetailsFromDNA, currentTime, true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process the closed loan import from DNA at ""(.*)""")]
|
|
public async void WhenIReadTheClosedLoanImportFromDNAAt(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ProcessClosedLoanImport(_closedLoansFromDNA, currentTime, string.Empty);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process the closed loan import with missing loan ""(.*)"" with date from DNA at ""(.*)"" and select from ""(.*)""")]
|
|
public async void WhenIProcessTheClosedLoanImportWithMissingLoanWithDateFromDNAAt(string missingLoanNumber, DateTime currentTime, DateTime newerThan)
|
|
{
|
|
try
|
|
{
|
|
var stringDate = newerThan.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
|
_importResult = await _importReadService.ProcessClosedLoanImport(_closedLoansFromDNA.Where(l => l.LoanNumber != missingLoanNumber).ToList(),
|
|
currentTime, stringDate);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process the missing active loans with detail from DNA at ""(.*)"" and export")]
|
|
public async void WhenIProcessTheMissingActiveLoansWithDetailFromDNAAtAndExport(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ProcessClosedLoansWithUpdates(_loanDetailsFromDNA, currentTime, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process the closed loan import with detail from DNA at ""(.*)""")]
|
|
public async void WhenIReadTheInitialClosedLoanImportFromDNAAt(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ProcessClosedLoansWithUpdates(_loanDetailsFromDNA, currentTime, false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I process the closed loan import with detail from DNA at ""(.*)"" and skip the export")]
|
|
public async void WhenIReadTheInitialClosedLoanImportFromDNAAtAndSkipTheExport(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ProcessClosedLoansWithUpdates(_loanDetailsFromDNA, currentTime, true);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I read this closed loan import file at ""(.*)""")]
|
|
public async void WhenIReadThisClosedLoanImportFileAt(DateTime currentTime)
|
|
{
|
|
try
|
|
{
|
|
_importResult = await _importReadService.ReadClosedLoanImportFile(_importStreamReader, _importFileName, currentTime);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_exception = ex;
|
|
}
|
|
}
|
|
|
|
[When(@"I get the record from the ImportTable")]
|
|
public async void WhenIGetTheRecordFromTheImportTable()
|
|
{
|
|
_importResult = (await _importRepository.GetAll().ToListAsync()).First();
|
|
}
|
|
|
|
[Then(@"the import has start date ""(.*)""")]
|
|
public void ThenTheImportHasStartDate(DateTime startDate)
|
|
{
|
|
Assert.Equal(startDate, _importResult.StartDate);
|
|
}
|
|
|
|
[Then(@"the import has an end date that is greater or equal to the start date")]
|
|
public void ThenTheImportHasAnEndDateThatIsGreaterOrEqualToTheStartDate()
|
|
{
|
|
Assert.True(_importResult.EndDate >= _importResult.StartDate);
|
|
}
|
|
|
|
[Then(@"the import has record count (.*)")]
|
|
public void ThenTheImportHasRecordCount(int recordCount)
|
|
{
|
|
Assert.Equal(recordCount, _importResult.RecordCount);
|
|
}
|
|
|
|
[Then(@"the import has success ""(.*)""")]
|
|
public void ThenTheImportHasSuccess(bool success)
|
|
{
|
|
Assert.Equal(success, _importResult.Success);
|
|
}
|
|
|
|
[Then(@"the import has file name ""(.*)""")]
|
|
public void ThenTheImportHasFileName(string fileName)
|
|
{
|
|
Assert.Equal(fileName, _importResult.FileName);
|
|
}
|
|
|
|
[Then(@"an exception is thrown")]
|
|
public void ThenAnExceptionIsThrown()
|
|
{
|
|
Assert.NotNull(_exception);
|
|
}
|
|
|
|
[Then(@"the import looks like")]
|
|
public void ThenTheImportLooksLike(Table table)
|
|
{
|
|
table.CompareToInstance(_importResult);
|
|
}
|
|
|
|
[Then(@"there is a record added to the Audit History table")]
|
|
public void ThenThereIsARecordAddedToTheAuditHistoryTable()
|
|
{
|
|
_mockAuditHistRepo.Verify(x => x.AddHistoriesAsync(It.IsAny<List<AuditHistory>>()));
|
|
}
|
|
|
|
[Then(@"no audit history record is added")]
|
|
public void ThenNoAuditHistoryRecordIsAdded()
|
|
{
|
|
_mockAuditHistRepo.Verify(x => x.AddHistoriesAsync(It.IsAny<List<AuditHistory>>()), Times.Never);
|
|
}
|
|
|
|
[Then(@"AddHistoriesAsync is called with (.*) history/ies having OldValue ""(.*)"" and NewValue ""(.*)""")]
|
|
public void ThenAddHistoriesAsyncIsCalledWithHistoryIesHavingOldValueAndNewValue(int number, string oldValue, string newValue)
|
|
{
|
|
_mockAuditHistRepo.Verify(x =>
|
|
x.AddHistoriesAsync(It.Is<List<AuditHistory>>(a => a.Count(x => x.NewValue == newValue && x.OldValue == oldValue) == number)));
|
|
}
|
|
|
|
[Then(@"AddHistoriesAsync is called with (.*) history/ies having ActivityType ""(.*)"" and AuditDescription ""(.*)""")]
|
|
public void ThenAddHistoriesAsyncIsCalledWithHistoryHavingActivityTypeAndAuditDescription(int number, string type, string description)
|
|
{
|
|
_mockAuditHistRepo.Verify(x =>
|
|
x.AddHistoriesAsync(It.Is<List<AuditHistory>>(a => a.Count(x => x.ActivityType == type && x.AuditDescription == description) == number)));
|
|
}
|
|
|
|
[Then(@"AddHistoriesAsync is called with (.*) history/ies having LoanNumber ""(.*)"" and MemberNumber ""(.*)""")]
|
|
public void ThenAddHistoriesAsyncIsCalledWithHistoryHavingLoanNumberAndMemberNumber(int number, string loanNumber, string memberNumber)
|
|
{
|
|
_mockAuditHistRepo.Verify(x =>
|
|
x.AddHistoriesAsync(It.Is<List<AuditHistory>>(a => a.Count(x => x.MemberNumber == memberNumber && x.LoanNumber == loanNumber) == number)));
|
|
}
|
|
|
|
[Then(@"ExportChargebacksAsync is called")]
|
|
public void ThenExportChargebacksAsyncIsCalled()
|
|
{
|
|
_mockExportService.Verify(x => x.ExportChargebacksAsync(It.IsAny<DateTime>()));
|
|
}
|
|
|
|
[Then(@"ExportChargebacksAsync is not called")]
|
|
public void ThenExportChargebacksAsyncIsNotCalled()
|
|
{
|
|
_mockExportService.Verify(x => x.ExportChargebacksAsync(It.IsAny<DateTime>()), Times.Never);
|
|
}
|
|
|
|
[Then(@"MarkReservesAndChargebacksAsExportedAsync is called")]
|
|
public void ThenMarkReservesAndChargebacksAsExportedAsyncIsCalled()
|
|
{
|
|
_mockExportService.Verify(x => x.MarkReservesAndChargebacksAsExportedAsync(It.IsAny<List<Loan>>(), It.IsAny<DateTime>()));
|
|
}
|
|
|
|
[Then(@"all loans have non-null ExportedChargebackDate")]
|
|
public void ThenAllLoansHaveNon_NullExportedChargebackDate()
|
|
{
|
|
Assert.DoesNotContain(_loansResult, l => l.ExportedChargebackDate == null);
|
|
}
|
|
|
|
[Then(@"ExportReservesAsync is called")]
|
|
public void ThenExportReservesAsyncIsCalled()
|
|
{
|
|
_mockExportService.Verify(x => x.ExportReservesAsync(It.IsAny<DateTime>()));
|
|
}
|
|
|
|
[Then(@"ExportReservesAsync is not called")]
|
|
public void ThenExportReservesAsyncIsNotCalled()
|
|
{
|
|
_mockExportService.Verify(x => x.ExportReservesAsync(It.IsAny<DateTime>()), Times.Never);
|
|
}
|
|
|
|
[Then(@"MarkReservesAsExportedAsync is called")]
|
|
public void ThenMarkReservesAsExportedAsyncIsCalled()
|
|
{
|
|
_mockExportService.Verify(x => x.MarkReservesAsExportedAsync(It.IsAny<List<Loan>>(), It.IsAny<DateTime>()));
|
|
}
|
|
|
|
[Then(@"all loans have non-null ExportedReserveDate")]
|
|
public void ThenAllLoansHaveNon_NullExportedReserveDate()
|
|
{
|
|
Assert.DoesNotContain(_loansResult, l => l.ExportedReserveDate == null);
|
|
}
|
|
|
|
[Then(@"the loans now look like")]
|
|
public async void ThenTheLoansNowLookLike(Table table)
|
|
{
|
|
_loansResult = await _loanRepository.GetAll().AsNoTracking().ToListAsync();
|
|
table.CompareToSet(_loansResult);
|
|
}
|
|
|
|
[Then(@"the dealers now look like")]
|
|
public async void ThenTheDealersNowLookLike(Table table)
|
|
{
|
|
_dealersResult = await _dealerRepository.GetAll().ToListAsync();
|
|
table.CompareToSet(_dealersResult);
|
|
}
|
|
|
|
[Then(@"the vehicle for LoanId (.*) looks like this")]
|
|
public void ThenTheVehicleForLoanIdLooksLikeThis(int loanId, Table table)
|
|
{
|
|
var result = _loansResult.FirstOrDefault(v => v.LoanId == loanId)?.Vehicle;
|
|
table.CompareToInstance<Vehicle>(result);
|
|
}
|
|
|
|
[Then(@"the vehicle for LoanId (.*) is null")]
|
|
public void ThenTheVehicleForLoanIdIsNull(int loanId)
|
|
{
|
|
Assert.Null(_loansResult.FirstOrDefault(v => v.LoanId == loanId).Vehicle);
|
|
}
|
|
|
|
[Then(@"the loans with details now look like")]
|
|
public void ThenTheLoansWithDetailsNowLookLike(Table table)
|
|
{
|
|
var loans = table.CreateInstance<Loan>();
|
|
_loansResult.Add(loans);
|
|
}
|
|
}
|
|
} |