Skip to content

Instantly share code, notes, and snippets.

@olegon
Last active February 20, 2021 14:44
Show Gist options
  • Save olegon/1a3d88ba558696cec8b87c5bcea1bfe4 to your computer and use it in GitHub Desktop.
Save olegon/1a3d88ba558696cec8b87c5bcea1bfe4 to your computer and use it in GitHub Desktop.
Unit testing .xlsx file parsing.
using System;
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using ClosedXML.Excel;
namespace application
{
public class App
{
private readonly IFakeRepository _fakeRepository;
private readonly CultureInfo _cultureInfo;
public App(
IFakeRepository fakeRepository
)
{
this._fakeRepository = fakeRepository;
this._cultureInfo = new CultureInfo("pt-BR");
}
public async Task ParseWorkbookFile(Stream stream)
{
using (var wb = new XLWorkbook(stream))
{
var sheet = wb.Worksheet(1);
foreach (var row in sheet.RowsUsed())
{
var rowNumber = row.RowNumber();
if (rowNumber > 2)
{
try
{
var accountId = GetAccountId(row);
var reason = GetReason(row);
var amount = GetAmount(row);
var description = GetDescription(row);
await _fakeRepository.InsertLine(
lineNumber: rowNumber,
status: "VALID",
accountId: accountId,
reason: reason,
amount: amount,
description: description
);
}
catch (System.Exception ex)
{
await _fakeRepository.InsertLine(
lineNumber: rowNumber,
status: "INVALID",
invalidReason: ex.Message
);
}
}
}
}
}
private string GetAccountId(IXLRow row)
{
var value = row.Cell(1).GetString();
return value;
}
private string GetReason(IXLRow row)
{
var value = row.Cell(2).GetString();
return value;
}
private double GetAmount(IXLRow row)
{
var value = row.Cell(3).GetString();
try
{
return double.Parse(value, NumberStyles.Currency, _cultureInfo);
}
catch (Exception ex)
{
throw new Exception("Amount out of the expected format.", ex);
}
}
private string GetDescription(IXLRow row)
{
var value = row.Cell(4).GetString();
return value;
}
}
}
using System.Threading.Tasks;
using application;
using application_tests.WorkbookUtils;
using FakeItEasy;
using NUnit.Framework;
namespace application_tests
{
public class AppTests
{
private IFakeRepository _fakeRepository;
private App _app;
[SetUp]
public void Setup()
{
_fakeRepository = A.Fake<IFakeRepository>();
_app = new App(
fakeRepository: _fakeRepository
);
}
[Test]
public async Task Test1()
{
var wbBuilder = new WorkbookBuilder();
wbBuilder.AddLine("V1");
wbBuilder.AddLine("AccountId", "Motivo", "Valor", "Descrição");
wbBuilder.AddLine("001", "Motivo 01", "R$ 10,00", "Desc 01");
wbBuilder.AddLine("002", "Motivo 02", "", "Desc 02");
using (var ms = wbBuilder.GetStream())
{
await _app.ParseWorkbookFile(ms);
}
A.CallTo(() => _fakeRepository.InsertLine(1, A<string>.Ignored, A<string>.Ignored)).MustNotHaveHappened();
A.CallTo(() => _fakeRepository.InsertLine(2, A<string>.Ignored, A<string>.Ignored)).MustNotHaveHappened();
A.CallTo(() => _fakeRepository.InsertLine(3, "VALID", "001", "Motivo 01", 10, "Desc 01")).MustHaveHappened();
A.CallTo(() => _fakeRepository.InsertLine(4, "INVALID", "Amount out of the expected format.")).MustHaveHappened();
}
}
}
using System.Threading.Tasks;
namespace application
{
public class FakeRepository : IFakeRepository
{
public async Task InsertLine(int lineNumber, string status, string accountId, string reason, double amount, string description)
{
await System.Console.Out.WriteLineAsync($"{lineNumber}, {status}, {accountId}, {reason}, {amount}, {description}");
}
public async Task InsertLine(int lineNumber, string status, string invalidReason)
{
await System.Console.Out.WriteLineAsync($"{lineNumber}, {status}, {invalidReason}");
}
}
}
using System.Threading.Tasks;
namespace application
{
public interface IFakeRepository
{
Task InsertLine(
int lineNumber,
string status,
string accountId,
string reason,
double amount,
string description
);
Task InsertLine(
int lineNumber,
string status,
string invalidReason
);
}
}
using System.Collections.Generic;
using System.IO;
using ClosedXML.Excel;
namespace application_tests.WorkbookUtils
{
public class WorkbookBuilder
{
private readonly List<object[]> _lines;
public WorkbookBuilder()
{
_lines = new List<object[]>();
}
public WorkbookBuilder AddLine(params object[] values)
{
this._lines.Add(values);
return this;
}
public Stream GetStream()
{
var ms = new MemoryStream();
using (var wb = new XLWorkbook())
{
var sheet = wb.AddWorksheet();
for (int lineNumber = 0; lineNumber < _lines.Count; lineNumber++)
{
var lineValues = _lines[lineNumber];
for (int columnNumber = 0; columnNumber < lineValues.Length; columnNumber++)
{
var cellValue = lineValues[columnNumber];
sheet.Row(lineNumber + 1).Cell(columnNumber + 1).SetValue(cellValue);
}
}
wb.SaveAs(ms);
}
return ms;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment