Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions jobs/Backend/Task/Currency.cs

This file was deleted.

23 changes: 0 additions & 23 deletions jobs/Backend/Task/ExchangeRate.cs

This file was deleted.

19 changes: 0 additions & 19 deletions jobs/Backend/Task/ExchangeRateProvider.cs

This file was deleted.

43 changes: 43 additions & 0 deletions jobs/Backend/Task/ExchangeRateUpdater.Tests/CnbXmlParserTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Linq;
using ExchangeRateUpdater.Exceptions;
using ExchangeRateUpdater.Models;
using ExchangeRateUpdater.Parsers;
using NUnit.Framework;

namespace ExchangeRateUpdater.Tests;

[TestFixture]
public class CnbXmlParserTests
{
[Test]
public void Parse_ValidXml_ReturnsCorrectExchangeRates()
{
// Arrange
var parser = new CnbXmlParser();
var baseCurrency = new Currency("CZK");

// Act
var rates = parser.Parse(TestData.CnbExchangeRateXml, baseCurrency).ToList();

// Assert

Assert.That(rates.Count, Is.EqualTo(31));

var audRate = rates.FirstOrDefault(r => r.TargetCurrency.Code == "AUD");
Assert.That(audRate.SourceCurrency.Code, Is.EqualTo("CZK"));
Assert.That(audRate.Value, Is.EqualTo(13.862m));
}
[Test]
public void Parse_InvalidXml_ReturnsCorrectExchangeRates()
{
// Arrange
var parser = new CnbXmlParser();
var baseCurrency = new Currency("CZK");

// Act
// Assert
Assert.Throws<ParsingException>(() => parser.Parse(TestData.InvalidCnbExchangeRateXml, baseCurrency));


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using ExchangeRateUpdater.Controllers;
using ExchangeRateUpdater.Models;
using ExchangeRateUpdater.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Moq;
using Moq.Protected;
using NUnit.Framework;

namespace ExchangeRateUpdater.Tests;

[TestFixture]
public class ExchangeRateControllerTests
{
private ExchangeRateController _controller;
private IConfiguration _configuration;
private Mock<IMemoryCache> _mockCache;
private ExchangeRateSettingsResolver _settingsResolver;
private ExchangeRateProvider _provider;

[SetUp]
public void Setup()
{
_configuration = new ConfigurationBuilder()
.SetBasePath(TestContext.CurrentContext.TestDirectory)
.AddJsonFile("appsettings.test.json", optional: false)
.Build();
_mockCache = new Mock<IMemoryCache>();


_settingsResolver = new ExchangeRateSettingsResolver(_configuration);
_mockCache.Setup(m => m.TryGetValue(It.IsAny<object>(), out It.Ref<object>.IsAny))
.Returns(false);
_mockCache.Setup(m => m.CreateEntry(It.IsAny<object>()))
.Returns(Mock.Of<ICacheEntry>());

var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(TestData.CnbExchangeRateXml),
});

var httpClient = new HttpClient(mockHttpMessageHandler.Object);

_provider = new ExchangeRateProvider(_mockCache.Object, httpClient, _settingsResolver, _configuration);
_controller = new ExchangeRateController(_provider);
}

[Test]
public async Task GetExchangeRates_ValidCurrencies_ReturnsOkWithRates()
{
// Arrange
var currencies = "EUR,USD";
var baseCurrency = TestData.BaseCurrency;
var expectedRates = new List<ExchangeRateResponse>
{
new () { SourceCurrency = baseCurrency, TargetCurrency = "EUR", ExchangeRate = 24.610m },
new () { SourceCurrency = baseCurrency, TargetCurrency = "USD", ExchangeRate = 21.331m}
};

// Act
var result = await _controller.GetExchangeRates(currencies, baseCurrency);

// Assert
Assert.That(result.Result, Is.InstanceOf<OkObjectResult>());
var okResult = result.Result as OkObjectResult;
Assert.That(okResult, Is.Not.Null);
var returnedRates = okResult.Value as IEnumerable<ExchangeRateResponse>;
Assert.That(returnedRates, Is.Not.Null);
Assert.That(returnedRates, Is.EquivalentTo(expectedRates)
.Using<ExchangeRateResponse>((x, y) => x.SourceCurrency == y.SourceCurrency &&
x.TargetCurrency == y.TargetCurrency &&
x.ExchangeRate == y.ExchangeRate));
}

[Test]
public async Task GetExchangeRates_EmptyCurrencies_ReturnsBadRequest()
{
// Arrange
var currencies = "";
var baseCurrency = TestData.BaseCurrency;

// Act
var result = await _controller.GetExchangeRates(currencies, baseCurrency);

// Assert
Assert.That(result.Result, Is.InstanceOf<BadRequestObjectResult>());
var badRequestResult = result.Result as BadRequestObjectResult;
Assert.That(badRequestResult, Is.Not.Null);
Assert.That(badRequestResult.Value, Is.EqualTo("Currency codes cannot be empty."));
}

[Test]
public async Task GetExchangeRates_ArgumentExceptionFromProvider_ReturnsBadRequest()
{
// Arrange
var currency = "TEST";
var baseCurrency = TestData.BaseCurrency;
var errorMessage = $"The following currencies are not allowed: {currency}";


// Act
var result = await _controller.GetExchangeRates(currency, baseCurrency);

// Assert
Assert.That(result.Result, Is.InstanceOf<BadRequestObjectResult>());
var badRequestResult = result.Result as BadRequestObjectResult;
Assert.That(badRequestResult, Is.Not.Null);
Assert.That(badRequestResult.Value, Is.EqualTo(errorMessage));
}

[TestCase(HttpStatusCode.ServiceUnavailable)]
[TestCase(HttpStatusCode.InternalServerError)]
[TestCase(HttpStatusCode.BadRequest)]

public async Task GetExchangeRates_ExchangeRateApiExceptionFromProvider_ReturnsServiceUnavailable(HttpStatusCode statusCode)
{
// Arrange
var currencies = "EUR";
var baseCurrency = TestData.BaseCurrency;

var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = statusCode,
});

var httpClient = new HttpClient(mockHttpMessageHandler.Object);

var provider = new ExchangeRateProvider( _mockCache.Object, httpClient, _settingsResolver, _configuration);
var controller = new ExchangeRateController(provider);

// Act
var result = await controller.GetExchangeRates(currencies, baseCurrency);

// Assert
Assert.That(result.Result, Is.InstanceOf<ObjectResult>());
var objectResult = result.Result as ObjectResult;
Assert.That(objectResult, Is.Not.Null);
Assert.That(objectResult.StatusCode, Is.GreaterThan(299));
Assert.That(objectResult.Value, Contains.Substring($"Service Unavailable: Failed to retrieve exchange rates from "));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using ExchangeRateUpdater.Exceptions;
using ExchangeRateUpdater.Models;
using ExchangeRateUpdater.Services;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Moq;
using Moq.Protected;
using NUnit.Framework;

namespace ExchangeRateUpdater.Tests;

[TestFixture]
public class ExchangeRateProviderTests
{
private Mock<IMemoryCache> _mockCache;
private IConfiguration _configuration;
private ExchangeRateSettingsResolver _settingsResolver;
private ExchangeRateProvider _provider;

[SetUp]
public void Setup()
{
_mockCache = new Mock<IMemoryCache>();

_configuration = new ConfigurationBuilder()
.SetBasePath(TestContext.CurrentContext.TestDirectory)
.AddJsonFile("appsettings.test.json", optional: false)
.Build();

_settingsResolver = new ExchangeRateSettingsResolver(_configuration);
_mockCache.Setup(m => m.TryGetValue(It.IsAny<object>(), out It.Ref<object>.IsAny))
.Returns(false);
_mockCache.Setup(m => m.CreateEntry(It.IsAny<object>()))
.Returns(Mock.Of<ICacheEntry>());

var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(TestData.CnbExchangeRateXml),
});

var httpClient = new HttpClient(mockHttpMessageHandler.Object);

_provider = new ExchangeRateProvider(_mockCache.Object, httpClient, _settingsResolver, _configuration);
}

[Test]
public async Task GetExchangeRates_ValidCurrencies_ReturnsRates()
{
// Arrange
var currencies = TestData.ValidCurrenciesForTest;
var baseCurrency = new Currency(TestData.BaseCurrency);
var expectedRates = new List<ExchangeRate>
{
new ExchangeRate(baseCurrency, new Currency("EUR"), 24.610m),
new ExchangeRate(baseCurrency, new Currency("USD"), 21.331m)
};

// Act
var result = (await _provider.GetExchangeRates(currencies, baseCurrency)).ToList();

// Assert
Assert.That(result, Is.EquivalentTo(expectedRates)
.Using<ExchangeRate>((x, y) => x.SourceCurrency.Code == y.SourceCurrency.Code &&
x.TargetCurrency.Code == y.TargetCurrency.Code &&
x.Value == y.Value));
}


[TestCase("TEST")]
[TestCase("")]
public void GetExchangeRates_InvalidBaseCurrency_ThrowsArgumentException(string currencyCode)
{
// Arrange
var currencies = TestData.ValidCurrenciesForTest;
var baseCurrency = new Currency(currencyCode);

// Act & Assert
Assert.ThrowsAsync<ArgumentException>(() => _provider.GetExchangeRates(currencies, baseCurrency));
}
[Test]
public void GetExchangeRates_NotImplementedBaseCurrency_ThrowsApiException()
{
// Arrange
var currencies = TestData.ValidCurrenciesForTest;
var baseCurrency = new Currency("USD");

// Act & Assert
Assert.ThrowsAsync<ExchangeRateApiException>(() => _provider.GetExchangeRates(currencies, baseCurrency));
}

[Test]
public void GetExchangeRates_InvalidTargetCurrency_ThrowsArgumentException()
{
// Arrange
var currencies = TestData.InvalidCurrenciesForTest;
var baseCurrency = new Currency(TestData.BaseCurrency);

// Act & Assert
Assert.ThrowsAsync<ArgumentException>(() => _provider.GetExchangeRates(currencies, baseCurrency));
}
[Test]
public void GetExchangeRates_EmptyTargetCurrencies_ThrowsArgumentException()
{
// Arrange
var baseCurrency = new Currency(TestData.BaseCurrency);

// Act & Assert
Assert.ThrowsAsync<ArgumentException>(() => _provider.GetExchangeRates([], baseCurrency));
}
}


Loading