Implement Delete and DeleteMany in TokensController.

This commit is contained in:
Denis-Cosmin Nutiu 2021-06-20 16:53:43 +03:00
parent 69017d915a
commit 169fed57a9
7 changed files with 235 additions and 13 deletions

View file

@ -11,6 +11,7 @@
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" /> <PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.15" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.15" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" /> <PackageReference Include="coverlet.collector" Version="1.2.0" />

View file

@ -124,7 +124,6 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
// Arrange // Arrange
await _mongoDb.DropAsync(); await _mongoDb.DropAsync();
var guids = new List<string>(); var guids = new List<string>();
await _mongoDb.DropAsync();
byte index = 0; byte index = 0;
var feedbackReceivers = items as FeedbackReceiver[] ?? items.ToArray(); var feedbackReceivers = items as FeedbackReceiver[] ?? items.ToArray();
foreach (var i in feedbackReceivers) foreach (var i in feedbackReceivers)
@ -134,6 +133,7 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
index += 1; index += 1;
guids.Add(i.Id); guids.Add(i.Id);
} }
await _mongoDb.FeedbackReceiverCollection.InsertManyAsync(feedbackReceivers); await _mongoDb.FeedbackReceiverCollection.InsertManyAsync(feedbackReceivers);
@ -157,7 +157,6 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
// Arrange // Arrange
await _mongoDb.DropAsync(); await _mongoDb.DropAsync();
var guids = new List<string>(); var guids = new List<string>();
await _mongoDb.DropAsync();
byte index = 0; byte index = 0;
var feedbackReceivers = items as FeedbackReceiver[] ?? items.ToArray(); var feedbackReceivers = items as FeedbackReceiver[] ?? items.ToArray();
foreach (var i in feedbackReceivers) foreach (var i in feedbackReceivers)
@ -167,19 +166,22 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
index += 1; index += 1;
guids.Add(i.Id); guids.Add(i.Id);
} }
await _mongoDb.FeedbackReceiverCollection.InsertManyAsync(feedbackReceivers); await _mongoDb.FeedbackReceiverCollection.InsertManyAsync(feedbackReceivers);
// Test // Test
var request = new HttpRequestMessage { var request = new HttpRequestMessage
{
Method = HttpMethod.Delete, Method = HttpMethod.Delete,
RequestUri = new Uri($"{_client.BaseAddress.AbsoluteUri}api/v1/FeedbackReceivers"), RequestUri = new Uri($"{_client.BaseAddress.AbsoluteUri}api/v1/FeedbackReceivers"),
// ReSharper disable once MethodHasAsyncOverload
Content = new StringContent(JsonConvert.SerializeObject(guids), Encoding.UTF8, "application/json") Content = new StringContent(JsonConvert.SerializeObject(guids), Encoding.UTF8, "application/json")
}; };
var httpResponse = await _client.SendAsync(request); var httpResponse = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.NoContent, httpResponse.StatusCode); Assert.Equal(HttpStatusCode.NoContent, httpResponse.StatusCode);
// Assert // Assert
var docs = await _mongoDb.FeedbackReceiverCollection.CountDocumentsAsync(FilterDefinition<FeedbackReceiver> var docs = await _mongoDb.FeedbackReceiverCollection.CountDocumentsAsync(FilterDefinition<FeedbackReceiver>
.Empty); .Empty);
Assert.Equal(0L, docs); Assert.Equal(0L, docs);

View file

@ -1,11 +1,17 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AutoFixture.Xunit2;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using Newtonsoft.Json;
using Retroactiune.Database; using Retroactiune.Database;
using Retroactiune.IntegrationTests.Retroactiune.WebAPI.Fixtures; using Retroactiune.IntegrationTests.Retroactiune.WebAPI.Fixtures;
using Retroactiune.Models; using Retroactiune.Models;
@ -83,7 +89,7 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
public async Task Test_GenerateTokens_NonExistingFeedbackReceiver() public async Task Test_GenerateTokens_NonExistingFeedbackReceiver()
{ {
var httpResponse = await _client.PostAsync("/api/v1/Tokens/", var httpResponse = await _client.PostAsync("/api/v1/Tokens/",
new StringContent("{\"numberOfTokens\": 1, \"feedbackReceiverId\": \"someid\"}", Encoding.UTF8, new StringContent("{\"numberOfTokens\": 1, \"feedbackReceiverId\": \"some_id\"}", Encoding.UTF8,
"application/json")); "application/json"));
Assert.Equal(HttpStatusCode.BadRequest, httpResponse.StatusCode); Assert.Equal(HttpStatusCode.BadRequest, httpResponse.StatusCode);
@ -97,5 +103,109 @@ namespace Retroactiune.IntegrationTests.Retroactiune.WebAPI.Controllers
Assert.Equal(HttpStatusCode.BadRequest, httpResponse.StatusCode); Assert.Equal(HttpStatusCode.BadRequest, httpResponse.StatusCode);
} }
// Delete nok, DeleteMany nok
[Theory, AutoData]
public async Task Test_Delete_Ok(IEnumerable<Token> tokens)
{
// Setup
await _mongoDb.DropAsync();
var guids = new List<string>();
var tokensArr = tokens as Token[] ?? tokens.ToArray();
byte index = 0;
foreach (var i in tokensArr)
{
i.Id = new BsonObjectId(new ObjectId(new byte[] {1, 2, index, 4, 5, 6, 7, 8, 9, index, 11, 14}))
.ToString();
i.FeedbackReceiverId = i.Id;
index += 1;
guids.Add(i.Id);
}
await _mongoDb.TokensCollection.InsertManyAsync(tokensArr);
Assert.Equal(tokensArr.Length,
await _mongoDb.TokensCollection.CountDocumentsAsync(FilterDefinition<Token>.Empty));
// Test
foreach (var guid in guids)
{
var response = await _client.DeleteAsync($"/api/v1/Tokens/{guid}", CancellationToken.None);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
}
// Assert
Assert.Equal(0, await _mongoDb.TokensCollection.CountDocumentsAsync(FilterDefinition<Token>.Empty));
}
[Fact]
public async Task Test_Delete_BadGuid()
{
// Setup
await _mongoDb.DropAsync();
// Test
var response = await _client.DeleteAsync("/api/v1/Tokens/batman", CancellationToken.None);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Theory, AutoData]
public async Task Test_DeleteMany_Ok(IEnumerable<Token> tokens)
{
// Setup
await _mongoDb.DropAsync();
var guids = new List<string>();
var tokensArr = tokens as Token[] ?? tokens.ToArray();
byte index = 0;
foreach (var i in tokensArr)
{
i.Id = new BsonObjectId(new ObjectId(new byte[] {1, 2, index, 4, 5, 6, 7, 8, 9, index, 11, 14}))
.ToString();
i.FeedbackReceiverId = i.Id;
index += 1;
guids.Add(i.Id);
}
await _mongoDb.TokensCollection.InsertManyAsync(tokensArr);
Assert.Equal(tokensArr.Length,
await _mongoDb.TokensCollection.CountDocumentsAsync(FilterDefinition<Token>.Empty));
// Test
var request = new HttpRequestMessage
{
Method = HttpMethod.Delete,
RequestUri = new Uri($"{_client.BaseAddress.AbsoluteUri}api/v1/Tokens"),
// ReSharper disable once MethodHasAsyncOverload
Content = new StringContent(JsonConvert.SerializeObject(guids), Encoding.UTF8, "application/json")
};
var response = await _client.SendAsync(request);
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
// Assert
Assert.Equal(0, await _mongoDb.TokensCollection.CountDocumentsAsync(FilterDefinition<Token>.Empty));
}
[Fact]
public async Task Test_DeleteMany_BadRequest()
{
// Setup
await _mongoDb.DropAsync();
// Test
var request = new HttpRequestMessage
{
Method = HttpMethod.Delete,
RequestUri = new Uri($"{_client.BaseAddress.AbsoluteUri}api/v1/Tokens"),
// ReSharper disable once MethodHasAsyncOverload
Content = new StringContent(JsonConvert.SerializeObject(new[] {"bad", "badder"}), Encoding.UTF8,
"application/json")
};
var response = await _client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
} }
} }

View file

@ -52,5 +52,73 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers
Assert.IsType<OkObjectResult>(result); Assert.IsType<OkObjectResult>(result);
tokens.Verify(i => i.GenerateTokensAsync(2, "froid", null), Times.Once); tokens.Verify(i => i.GenerateTokensAsync(2, "froid", null), Times.Once);
} }
[Fact]
public async Task Test_Delete_Ok()
{
// Arrange
var feedbackService = new Mock<IFeedbackReceiverService>();
var tokens = new Mock<ITokensService>();
// Test
var controller = new TokensController(feedbackService.Object, tokens.Object);
var result = await controller.DeleteToken("my_guid");
// Assert
Assert.IsType<NoContentResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid"}), Times.Once);
}
[Fact]
public async Task Test_Delete_BadRequest()
{
// Arrange
var feedbackService = new Mock<IFeedbackReceiverService>();
var tokens = new Mock<ITokensService>();
tokens.Setup(i => i.DeleteTokens(It.IsAny<IEnumerable<string>>()))
.Throws(new GenericServiceException("op fail"));
// Test
var controller = new TokensController(feedbackService.Object, tokens.Object);
var result = await controller.DeleteToken("my_guid");
// Assert
Assert.IsType<BadRequestObjectResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid"}), Times.Once);
}
[Fact]
public async Task Test_DeleteMany_Ok()
{
// Arrange
var feedbackService = new Mock<IFeedbackReceiverService>();
var tokens = new Mock<ITokensService>();
// Test
var controller = new TokensController(feedbackService.Object, tokens.Object);
var result = await controller.DeleteTokens(new[] {"my_guid", "b"});
// Assert
Assert.IsType<NoContentResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid", "b"}), Times.Once);
}
[Fact]
public async Task Test_DeleteMany_BadRequest()
{
// Arrange
var feedbackService = new Mock<IFeedbackReceiverService>();
var tokens = new Mock<ITokensService>();
tokens.Setup(i => i.DeleteTokens(It.IsAny<IEnumerable<string>>()))
.Throws(new GenericServiceException("op fail"));
// Test
var controller = new TokensController(feedbackService.Object, tokens.Object);
var result = await controller.DeleteTokens(new[] {"my_guid", "b"});
// Assert
Assert.IsType<BadRequestObjectResult>(result);
tokens.Verify(i => i.DeleteTokens(new[] {"my_guid", "b"}), Times.Once);
}
} }
} }

View file

@ -80,5 +80,39 @@ namespace Retroactiune.Tests.Retroactiune.WebAPI.Services
It.IsAny<InsertManyOptions>(), It.IsAny<InsertManyOptions>(),
It.IsAny<CancellationToken>()), Times.Once); It.IsAny<CancellationToken>()), Times.Once);
} }
[Fact]
public async Task Test_DeleteTokens_Ok()
{
// Setup
var mongoDatabaseMock = new Mock<IMongoDatabase>();
var mongoClientMock = new Mock<IMongoClient>();
var mongoSettingsMock = new Mock<IDatabaseSettings>();
var mongoCollectionMock = new Mock<IMongoCollection<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);
// Test
var service = new TokensService(mongoClientMock.Object, mongoSettingsMock.Object);
await service.DeleteTokens(new[] {"test_id"});
// Assert
mongoCollectionMock.Verify(
i
=> i.DeleteManyAsync(
It.IsAny<FilterDefinition<Token>>(),
It.IsAny<CancellationToken>()), Times.Once);
}
} }
} }

View file

@ -68,7 +68,6 @@ namespace Retroactiune.Controllers
[ProducesResponseType(typeof(BasicResponse),StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(BasicResponse),StatusCodes.Status400BadRequest)]
public async Task<IActionResult> DeleteTokens([Required] IEnumerable<string> tokenIds) public async Task<IActionResult> DeleteTokens([Required] IEnumerable<string> tokenIds)
{ {
// TODO: Unit test, integration test.
try try
{ {
await _tokensService.DeleteTokens(tokenIds); await _tokensService.DeleteTokens(tokenIds);
@ -93,12 +92,21 @@ namespace Retroactiune.Controllers
[HttpDelete("{guid}")] [HttpDelete("{guid}")]
[ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<NoContentResult> DeleteToken( public async Task<IActionResult> DeleteToken(
[StringLength(24, ErrorMessage = "invalid guid, must be 24 characters", MinimumLength = 24)] string guid) [StringLength(24, ErrorMessage = "invalid guid, must be 24 characters", MinimumLength = 24)] string guid)
{ {
// TODO: Unit test, integration test. try
await _tokensService.DeleteTokens(new []{ guid }); {
return NoContent(); await _tokensService.DeleteTokens(new []{ guid });
return NoContent();
}
catch (GenericServiceException e)
{
return BadRequest(new BasicResponse
{
Message = e.Message
});
}
} }
} }
} }

View file

@ -42,7 +42,6 @@ namespace Retroactiune.Services
public async Task DeleteTokens(IEnumerable<string> tokenIds) public async Task DeleteTokens(IEnumerable<string> tokenIds)
{ {
// TODO: Unit test.
try try
{ {
var filter = new FilterDefinitionBuilder<Token>(); var filter = new FilterDefinitionBuilder<Token>();