Add unit & integration tests for TokensController.cs
This commit is contained in:
parent
32054fea3c
commit
56bbb68dda
10 changed files with 362 additions and 12 deletions
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json.Serialization;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
@ -33,7 +34,7 @@ namespace Retroactiune.Core.Entities
|
|||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
return RuntimeHelpers.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json.Serialization;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
@ -31,13 +32,14 @@ namespace Retroactiune.Core.Entities
|
|||
return false;
|
||||
}
|
||||
|
||||
return string.Equals(Id, convertedObj.Id) && string.Equals(FeedbackReceiverId, convertedObj.FeedbackReceiverId) &&
|
||||
TimeUsed == convertedObj.TimeUsed && ExpiryTime == convertedObj.ExpiryTime;
|
||||
return string.Equals(Id, convertedObj.Id) &&
|
||||
string.Equals(FeedbackReceiverId, convertedObj.FeedbackReceiverId) &&
|
||||
(CreatedAt - convertedObj.CreatedAt).Milliseconds == 0;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
return RuntimeHelpers.GetHashCode(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,13 +56,12 @@ namespace Retroactiune.Core.Services
|
|||
|
||||
public async Task<IEnumerable<Token>> ListTokens(TokenListFilters filters)
|
||||
{
|
||||
// TODO Write unit tests.
|
||||
var filterBuilder = new FilterDefinitionBuilder<Token>();
|
||||
var activeFilters = new List<FilterDefinition<Token>>();
|
||||
var tokensListFilter = FilterDefinition<Token>.Empty;
|
||||
|
||||
// Filter by token ids.
|
||||
if (filters.Ids.Any())
|
||||
if (filters.Ids != null && filters.Ids.Any())
|
||||
{
|
||||
activeFilters.Add(filterBuilder.In(i => i.Id, filters.Ids));
|
||||
}
|
||||
|
|
|
@ -24,12 +24,12 @@ using JsonSerializer = System.Text.Json.JsonSerializer;
|
|||
namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
|
||||
{
|
||||
[Collection("IntegrationTests")]
|
||||
public class TestFeedbackReceiver : IClassFixture<WebApiTestingFactory>
|
||||
public class TestFeedbackReceiversController : IClassFixture<WebApiTestingFactory>
|
||||
{
|
||||
private readonly MongoDbFixture _mongoDb;
|
||||
private readonly HttpClient _client;
|
||||
|
||||
public TestFeedbackReceiver(WebApiTestingFactory factory)
|
||||
public TestFeedbackReceiversController(WebApiTestingFactory factory)
|
||||
{
|
||||
_client = factory.CreateClient();
|
||||
var dbSettings = factory.Services.GetService<IOptions<DatabaseSettings>>();
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
|
@ -7,6 +8,7 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture.Xunit2;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
|
@ -16,16 +18,17 @@ using Retroactiune.Core.Entities;
|
|||
using Retroactiune.Infrastructure;
|
||||
using Retroactiune.IntegrationTests.Retroactiune.WebAPI.Fixtures;
|
||||
using Xunit;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
|
||||
{
|
||||
[Collection("IntegrationTests")]
|
||||
public class TestTokens : IClassFixture<WebApiTestingFactory>
|
||||
public class TestTokensController : IClassFixture<WebApiTestingFactory>
|
||||
{
|
||||
private readonly MongoDbFixture _mongoDb;
|
||||
private readonly HttpClient _client;
|
||||
|
||||
public TestTokens(WebApiTestingFactory factory)
|
||||
public TestTokensController(WebApiTestingFactory factory)
|
||||
{
|
||||
_client = factory.CreateClient();
|
||||
var dbSettings = factory.Services.GetService<IOptions<DatabaseSettings>>();
|
||||
|
@ -207,5 +210,168 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
|
|||
// Assert
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_NoFilter_Empty()
|
||||
{
|
||||
// Setup
|
||||
await _mongoDb.DropAsync();
|
||||
|
||||
// Test
|
||||
var response = await _client.GetAsync("api/v1/Tokens");
|
||||
var items = JsonSerializer.Deserialize<List<Token>>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Empty(items);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_NoFilter()
|
||||
{
|
||||
// Setup
|
||||
await _mongoDb.DropAsync();
|
||||
var timeNow = DateTime.UtcNow;
|
||||
var tokens = TokensFixture.Generate(10, timeNow);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(tokens);
|
||||
|
||||
// Test
|
||||
var response = await _client.GetAsync("api/v1/Tokens");
|
||||
var items = JsonSerializer.Deserialize<List<Token>>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(tokens.Count, items.Count);
|
||||
for (var i = 0; i < tokens.Count; i++)
|
||||
{
|
||||
Assert.Equal(tokens[i], items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_Filter_FeedbackReceiverId()
|
||||
{
|
||||
// Setup
|
||||
await _mongoDb.DropAsync();
|
||||
|
||||
var timeNow = DateTime.UtcNow;
|
||||
var tokens = TokensFixture.Generate(13, timeNow);
|
||||
var expectedTokens = TokensFixture.Generate(1, timeNow);
|
||||
|
||||
var qb = new QueryBuilder
|
||||
{
|
||||
{"FeedbackReceiverId", expectedTokens[0].FeedbackReceiverId},
|
||||
};
|
||||
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(tokens);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(expectedTokens);
|
||||
|
||||
// Test
|
||||
var response = await _client.GetAsync($"api/v1/Tokens{qb}");
|
||||
var items = JsonSerializer.Deserialize<List<Token>>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Single(items);
|
||||
Assert.Equal(expectedTokens[0], items[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_Filter_Ids()
|
||||
{
|
||||
// Setup
|
||||
await _mongoDb.DropAsync();
|
||||
|
||||
var timeNow = DateTime.UtcNow;
|
||||
var tokens = TokensFixture.Generate(13, timeNow);
|
||||
var expectedTokens = TokensFixture.Generate(1, timeNow);
|
||||
|
||||
var qb = new QueryBuilder
|
||||
{
|
||||
{"Ids", expectedTokens[0].Id},
|
||||
};
|
||||
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(tokens);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(expectedTokens);
|
||||
|
||||
// Test
|
||||
var response = await _client.GetAsync($"api/v1/Tokens{qb}");
|
||||
var items = JsonSerializer.Deserialize<List<Token>>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Single(items);
|
||||
Assert.Equal(expectedTokens[0], items[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_Filter_CreatedRange()
|
||||
{
|
||||
// Setup
|
||||
await _mongoDb.DropAsync();
|
||||
|
||||
var timeNow = DateTime.UtcNow;
|
||||
|
||||
var oldTokens = TokensFixture.Generate(13, timeNow.AddDays(-10));
|
||||
var futureTokens = TokensFixture.Generate(13, timeNow.AddDays(10));
|
||||
var expectedTokens = TokensFixture.Generate(5, timeNow);
|
||||
|
||||
var qb = new QueryBuilder
|
||||
{
|
||||
{"CreatedAfter", timeNow.AddDays(-3).ToString(CultureInfo.InvariantCulture)},
|
||||
{"CreatedBefore", timeNow.AddDays(3).ToString(CultureInfo.InvariantCulture)},
|
||||
};
|
||||
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(oldTokens);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(expectedTokens);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(futureTokens);
|
||||
|
||||
// Test
|
||||
var response = await _client.GetAsync($"api/v1/Tokens{qb}");
|
||||
var items = JsonSerializer.Deserialize<List<Token>>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedTokens.Count, items.Count);
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
Assert.Equal(expectedTokens[i], items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_Filter_UsedRange()
|
||||
{
|
||||
// Setup
|
||||
await _mongoDb.DropAsync();
|
||||
|
||||
var timeNow = DateTime.UtcNow;
|
||||
|
||||
var oldTokens = TokensFixture.Generate(13, timeNow.AddDays(-10));
|
||||
var futureTokens = TokensFixture.Generate(13, timeNow.AddDays(10));
|
||||
var expectedTokens = TokensFixture.Generate(5, timeNow, null, null, timeNow);
|
||||
|
||||
var qb = new QueryBuilder
|
||||
{
|
||||
{"UsedAfter", timeNow.AddDays(-3).ToString(CultureInfo.InvariantCulture)},
|
||||
{"UsedBefore", timeNow.AddDays(3).ToString(CultureInfo.InvariantCulture)},
|
||||
};
|
||||
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(oldTokens);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(expectedTokens);
|
||||
await _mongoDb.TokensCollection.InsertManyAsync(futureTokens);
|
||||
|
||||
// Test
|
||||
var response = await _client.GetAsync($"api/v1/Tokens{qb}");
|
||||
var items = JsonSerializer.Deserialize<List<Token>>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(expectedTokens.Count, items.Count);
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
Assert.Equal(expectedTokens[i], items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MongoDB.Bson;
|
||||
using Retroactiune.Core.Entities;
|
||||
|
||||
namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Fixtures
|
||||
{
|
||||
public static class TokensFixture
|
||||
{
|
||||
public static List<Token> Generate(int number, DateTime createdAt, ObjectId? feedbackReceiverId = null,
|
||||
DateTime? expiryTime = null, DateTime? timeUsed = null)
|
||||
{
|
||||
var list = new List<Token>();
|
||||
for (var i = 0; i < number; i++)
|
||||
{
|
||||
var finalFeedbackReceiverId = ObjectId.GenerateNewId().ToString();
|
||||
if (feedbackReceiverId != null)
|
||||
{
|
||||
finalFeedbackReceiverId = feedbackReceiverId.ToString();
|
||||
}
|
||||
|
||||
|
||||
list.Add(new Token
|
||||
{
|
||||
Id = ObjectId.GenerateNewId().ToString(),
|
||||
FeedbackReceiverId = finalFeedbackReceiverId,
|
||||
CreatedAt = createdAt,
|
||||
TimeUsed = timeUsed,
|
||||
ExpiryTime = expiryTime
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MongoDB.Driver;
|
||||
|
@ -114,5 +115,91 @@ namespace Retroactiune.Tests.Retroactiune.Core.Services
|
|||
It.IsAny<FilterDefinition<Token>>(),
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_NoFilters_Ok()
|
||||
{
|
||||
// Setup
|
||||
var mongoDatabaseMock = new Mock<IMongoDatabase>();
|
||||
var mongoClientMock = new Mock<IMongoClient>();
|
||||
var mongoSettingsMock = new Mock<IDatabaseSettings>();
|
||||
var mongoCollectionMock = new Mock<IMongoCollection<Token>>();
|
||||
var mongoCursorMock = new Mock<IAsyncCursor<Token>>();
|
||||
|
||||
mongoSettingsMock.SetupGet(i => i.DatabaseName).Returns("MyDB");
|
||||
mongoSettingsMock.SetupGet(i => i.TokensCollectionName).Returns("tokens");
|
||||
|
||||
mongoClientMock
|
||||
.Setup(stub => stub.GetDatabase(It.IsAny<string>(),
|
||||
It.IsAny<MongoDatabaseSettings>()))
|
||||
.Returns(mongoDatabaseMock.Object);
|
||||
|
||||
mongoDatabaseMock
|
||||
.Setup(i => i.GetCollection<Token>(It.IsAny<string>(),
|
||||
It.IsAny<MongoCollectionSettings>()))
|
||||
.Returns(mongoCollectionMock.Object);
|
||||
|
||||
mongoCollectionMock.Setup(i => i.FindAsync(It.IsAny<FilterDefinition<Token>>(),
|
||||
It.IsAny<FindOptions<Token, Token>>(), It.IsAny<CancellationToken>())).ReturnsAsync(mongoCursorMock.Object);
|
||||
|
||||
// Test
|
||||
var service = new TokenService(mongoClientMock.Object, mongoSettingsMock.Object);
|
||||
var result = await service.ListTokens(new TokenListFilters());
|
||||
|
||||
// Assert
|
||||
Assert.IsType<List<Token>>(result);
|
||||
mongoCollectionMock.Verify(
|
||||
i
|
||||
=> i.FindAsync(It.IsAny<FilterDefinition<Token>>(),
|
||||
It.IsAny<FindOptions<Token, Token>>(),
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_Filters_Ok()
|
||||
{
|
||||
// Setup
|
||||
var mongoDatabaseMock = new Mock<IMongoDatabase>();
|
||||
var mongoClientMock = new Mock<IMongoClient>();
|
||||
var mongoSettingsMock = new Mock<IDatabaseSettings>();
|
||||
var mongoCollectionMock = new Mock<IMongoCollection<Token>>();
|
||||
var mongoCursorMock = new Mock<IAsyncCursor<Token>>();
|
||||
|
||||
mongoSettingsMock.SetupGet(i => i.DatabaseName).Returns("MyDB");
|
||||
mongoSettingsMock.SetupGet(i => i.TokensCollectionName).Returns("tokens");
|
||||
|
||||
mongoClientMock
|
||||
.Setup(stub => stub.GetDatabase(It.IsAny<string>(),
|
||||
It.IsAny<MongoDatabaseSettings>()))
|
||||
.Returns(mongoDatabaseMock.Object);
|
||||
|
||||
mongoDatabaseMock
|
||||
.Setup(i => i.GetCollection<Token>(It.IsAny<string>(),
|
||||
It.IsAny<MongoCollectionSettings>()))
|
||||
.Returns(mongoCollectionMock.Object);
|
||||
|
||||
mongoCollectionMock.Setup(i => i.FindAsync(It.IsAny<FilterDefinition<Token>>(),
|
||||
It.IsAny<FindOptions<Token, Token>>(), It.IsAny<CancellationToken>())).ReturnsAsync(mongoCursorMock.Object);
|
||||
|
||||
// Test
|
||||
var service = new TokenService(mongoClientMock.Object, mongoSettingsMock.Object);
|
||||
var result = await service.ListTokens(new TokenListFilters
|
||||
{
|
||||
Ids = new []{"a", "b"},
|
||||
FeedbackReceiverId = "abc",
|
||||
CreatedAfter = DateTime.UtcNow,
|
||||
CreatedBefore = DateTime.UtcNow,
|
||||
UsedAfter = DateTime.UtcNow,
|
||||
UsedBefore = DateTime.UtcNow
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.IsType<List<Token>>(result);
|
||||
mongoCollectionMock.Verify(
|
||||
i
|
||||
=> i.FindAsync(It.IsAny<FilterDefinition<Token>>(),
|
||||
It.IsAny<FindOptions<Token, Token>>(),
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ using Moq;
|
|||
using Retroactiune.Controllers;
|
||||
using Retroactiune.Core.Entities;
|
||||
using Retroactiune.Core.Interfaces;
|
||||
using Retroactiune.Core.Services;
|
||||
using Retroactiune.DataTransferObjects;
|
||||
using Xunit;
|
||||
|
||||
|
@ -86,6 +87,27 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
|
|||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteMany_BadRequest()
|
||||
{
|
||||
// Arrange
|
||||
var mapper = TestUtils.GetMapper();
|
||||
var mockService = new Mock<IFeedbackReceiverService>();
|
||||
var logger = new Mock<ILogger<FeedbackReceiversController>>();
|
||||
mockService.Setup(i => i.DeleteManyAsync(It.IsAny<IEnumerable<string>>()))
|
||||
.ThrowsAsync(new GenericServiceException("op failed"));
|
||||
|
||||
// Test
|
||||
var controller = new FeedbackReceiversController(mockService.Object, mapper, null, logger.Object);
|
||||
var items = new[] {"bad_guid_but_unit_test_works_cause_validation_doesnt", "2", "3"};
|
||||
var result = await controller.DeleteMany(items);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<BadRequestObjectResult>(result);
|
||||
mockService.Verify(s => s.DeleteManyAsync(items),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Get_Successful()
|
||||
{
|
||||
|
|
|
@ -134,5 +134,43 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
|
|||
Assert.IsType<BadRequestObjectResult>(result);
|
||||
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid", "b"}), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_Ok()
|
||||
{
|
||||
// Arrange
|
||||
var mapper = TestUtils.GetMapper();
|
||||
var feedbackService = new Mock<IFeedbackReceiverService>();
|
||||
var tokens = new Mock<ITokensService>();
|
||||
var logger = new Mock<ILogger<TokensController>>();
|
||||
|
||||
// Test
|
||||
var controller = new TokensController(feedbackService.Object, tokens.Object, logger.Object, mapper);
|
||||
var result = await controller.ListTokens(null);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<OkObjectResult>(result);
|
||||
tokens.Verify(i => i.ListTokens(It.IsAny<TokenListFilters>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test_ListTokens_BadRequest()
|
||||
{
|
||||
// Arrange
|
||||
var mapper = TestUtils.GetMapper();
|
||||
var feedbackService = new Mock<IFeedbackReceiverService>();
|
||||
var tokens = new Mock<ITokensService>();
|
||||
var logger = new Mock<ILogger<TokensController>>();
|
||||
tokens.Setup(i => i.ListTokens(It.IsAny<TokenListFilters>()))
|
||||
.Throws(new GenericServiceException("op fail"));
|
||||
|
||||
// Test
|
||||
var controller = new TokensController(feedbackService.Object, tokens.Object, logger.Object, mapper);
|
||||
var result = await controller.ListTokens(null);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<BadRequestObjectResult>(result);
|
||||
tokens.Verify(i => i.ListTokens(It.IsAny<TokenListFilters>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,7 +42,6 @@ namespace Retroactiune.Controllers
|
|||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> ListTokens([FromQuery] ListTokensFiltersDto filtersDto)
|
||||
{
|
||||
// TODO: Write unit & integration tests.
|
||||
try
|
||||
{
|
||||
var tokenFilters = _mapper.Map<TokenListFilters>(filtersDto);
|
||||
|
|
Loading…
Reference in a new issue