diff --git a/Retroactiune.Tests/Retroactiune.Tests.csproj b/Retroactiune.Tests/Retroactiune.Tests.csproj index 954cca7..183cdc4 100644 --- a/Retroactiune.Tests/Retroactiune.Tests.csproj +++ b/Retroactiune.Tests/Retroactiune.Tests.csproj @@ -7,9 +7,18 @@ - - + + + + + + + + + + + diff --git a/Retroactiune.Tests/Retroactiune.WebAPI/Controllers/TestFeedbackReceiverController.cs b/Retroactiune.Tests/Retroactiune.WebAPI/Controllers/TestFeedbackReceiverController.cs new file mode 100644 index 0000000..a39ddd1 --- /dev/null +++ b/Retroactiune.Tests/Retroactiune.WebAPI/Controllers/TestFeedbackReceiverController.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using AutoFixture.Xunit2; +using Microsoft.AspNetCore.Mvc; +using Moq; +using Retroactiune.Controllers; +using Retroactiune.Models; +using Retroactiune.Services; +using Xunit; + +namespace Retroactiune.Tests.Retroactiune.WebAPI.Controllers +{ + public class TestFeedbackReceiverController + { + [Fact] + public async Task Post_Successful_Creation_No_items() + { + var mapper = TestUtils.GetMapper(); + var mockService = new Mock(); + + // Test + var controller = new FeedbackReceiverController(mockService.Object, mapper, null); + var result = await controller.Post(new List()); + + // Assert, null because we don't have the ApiBehaviourOptions set, which would generate the IActionResult for the invalid input. + Assert.Null(result); + } + + [Theory, AutoData] + public async Task Post_Successful_Creation_Two_items(IEnumerable items) + { + var mapper = TestUtils.GetMapper(); + var mockService = new Mock(); + + // Test + var controller = new FeedbackReceiverController(mockService.Object, mapper, null); + var result = await controller.Post(items); + + // Assert + Assert.IsType(result); + } + } +} \ No newline at end of file diff --git a/Retroactiune.Tests/Retroactiune.WebAPI/TestUtils.cs b/Retroactiune.Tests/Retroactiune.WebAPI/TestUtils.cs new file mode 100644 index 0000000..6aa1da6 --- /dev/null +++ b/Retroactiune.Tests/Retroactiune.WebAPI/TestUtils.cs @@ -0,0 +1,17 @@ +using AutoMapper; + +namespace Retroactiune.Tests.Retroactiune.WebAPI +{ + public static class TestUtils + { + public static IMapper GetMapper() + { + var configuration = new MapperConfiguration(cfg => + { + cfg.AddProfile(); + }); + var mapper = configuration.CreateMapper(); + return mapper; + } + } +} \ No newline at end of file diff --git a/Retroactiune.Tests/Retroactiune.WebAPI/UnitTest1.cs b/Retroactiune.Tests/Retroactiune.WebAPI/UnitTest1.cs deleted file mode 100644 index 51b7044..0000000 --- a/Retroactiune.Tests/Retroactiune.WebAPI/UnitTest1.cs +++ /dev/null @@ -1,19 +0,0 @@ -using NUnit.Framework; - -namespace Retroactiune.Tests -{ - public class Tests - { - [SetUp] - public void Setup() - { - } - - [Test] - public void Test1() - { - // TODO: Test WebAPI, todo, Test service. =) :( - Assert.Pass(); - } - } -} \ No newline at end of file diff --git a/Retroactiune.Tests/UnitTest1.cs b/Retroactiune.Tests/UnitTest1.cs new file mode 100644 index 0000000..144809c --- /dev/null +++ b/Retroactiune.Tests/UnitTest1.cs @@ -0,0 +1,13 @@ +using System; +using Xunit; + +namespace Retroactiune.Tests +{ + public class UnitTest1 + { + [Fact] + public void Test1() + { + } + } +} \ No newline at end of file diff --git a/Retroactiune.WebAPI/Controllers/FeedbackReceiverController.cs b/Retroactiune.WebAPI/Controllers/FeedbackReceiverController.cs index 38e7ea6..e8395cb 100644 --- a/Retroactiune.WebAPI/Controllers/FeedbackReceiverController.cs +++ b/Retroactiune.WebAPI/Controllers/FeedbackReceiverController.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using AutoMapper; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Retroactiune.Models; using Retroactiune.Services; @@ -13,13 +16,52 @@ namespace Retroactiune.Controllers [Route("api/v1/[controller]")] public class FeedbackReceiverController : ControllerBase { - private readonly FeedbackReceiverService _service; + private readonly IOptions _apiBehaviorOptions; + private readonly IFeedbackReceiverService _service; private readonly IMapper _mapper; - public FeedbackReceiverController(FeedbackReceiverService service, IMapper mapper) + public FeedbackReceiverController(IFeedbackReceiverService service, IMapper mapper, + IOptions apiBehaviorOptions) { _service = service; _mapper = mapper; + _apiBehaviorOptions = apiBehaviorOptions; + } + + + /// + /// Inserts FeedbackReceivers into the database. + /// + /// The list of FeedbackReceivers + /// A BasicResponse indicating success. + /// Returns the newly created item + /// If the items is invalid + [HttpPost] + [ProducesResponseType(typeof(BasicResponse), StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task Post([Required] IEnumerable items) + { + var feedbackReceiversDto = items.ToList(); + if (!feedbackReceiversDto.Any()) + { + ModelState.AddModelError(nameof(IEnumerable), + "At least one FeedbackReceiver item is required."); + return _apiBehaviorOptions?.Value.InvalidModelStateResponseFactory(ControllerContext); + } + + var mappedItems = feedbackReceiversDto.Select(i => + { + var result = _mapper.Map(i); + result.CreatedAt = DateTime.UtcNow; + return result; + }); + + await _service.CreateManyAsync(mappedItems); + + return Ok(new BasicResponse() + { + Message = "Items created successfully!" + }); } [HttpDelete("{id}")] @@ -29,25 +71,6 @@ namespace Retroactiune.Controllers return NoContent(); } - - [HttpPost] - public async Task Post(IEnumerable items) - { - var mappedItems = items.ToList().Select(i => - { - var result = _mapper.Map(i); - result.CreatedAt = DateTime.UtcNow; - return result; - }); - - await _service.CreateMany(mappedItems); - - return new BasicResponse() - { - Message = "Items created successfully!" - }; - } - [HttpGet("{id}")] public BasicResponse Get(long id) { diff --git a/Retroactiune.WebAPI/Models/MappingProfile.cs b/Retroactiune.WebAPI/MappingProfile.cs similarity index 80% rename from Retroactiune.WebAPI/Models/MappingProfile.cs rename to Retroactiune.WebAPI/MappingProfile.cs index 6085e66..3263332 100644 --- a/Retroactiune.WebAPI/Models/MappingProfile.cs +++ b/Retroactiune.WebAPI/MappingProfile.cs @@ -1,6 +1,7 @@ using AutoMapper; +using Retroactiune.Models; -namespace Retroactiune.Models +namespace Retroactiune { public class MappingProfile : Profile { diff --git a/Retroactiune.WebAPI/Properties/launchSettings.json b/Retroactiune.WebAPI/Properties/launchSettings.json index db82e76..9c37f5f 100644 --- a/Retroactiune.WebAPI/Properties/launchSettings.json +++ b/Retroactiune.WebAPI/Properties/launchSettings.json @@ -19,7 +19,7 @@ }, "Retroactiune": { "commandName": "Project", - "launchBrowser": true, + "launchBrowser": false, "launchUrl": "", "applicationUrl": "https://localhost:5001;http://localhost:5000", "environmentVariables": { diff --git a/Retroactiune.WebAPI/Services/FeedbackReceiverService.cs b/Retroactiune.WebAPI/Services/FeedbackReceiverService.cs index 77ae1f3..e88a329 100644 --- a/Retroactiune.WebAPI/Services/FeedbackReceiverService.cs +++ b/Retroactiune.WebAPI/Services/FeedbackReceiverService.cs @@ -12,7 +12,7 @@ namespace Retroactiune.Services /// Service that simplifies access to the database for managing FeedbackReceiver items. /// /// - public class FeedbackReceiverService + public class FeedbackReceiverService : IFeedbackReceiverService { private readonly IMongoCollection _collection; private readonly ILogger _logger; @@ -25,7 +25,7 @@ namespace Retroactiune.Services _logger = logger; } - public async Task CreateMany(IEnumerable items) + public async Task CreateManyAsync(IEnumerable items) { try { diff --git a/Retroactiune.WebAPI/Services/IFeedbackReceiverService.cs b/Retroactiune.WebAPI/Services/IFeedbackReceiverService.cs new file mode 100644 index 0000000..468f418 --- /dev/null +++ b/Retroactiune.WebAPI/Services/IFeedbackReceiverService.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Retroactiune.Models; + +namespace Retroactiune.Services +{ + public interface IFeedbackReceiverService + { + public Task CreateManyAsync(IEnumerable items); + } +} \ No newline at end of file diff --git a/Retroactiune.WebAPI/Startup.cs b/Retroactiune.WebAPI/Startup.cs index 87a780b..9a0e57d 100644 --- a/Retroactiune.WebAPI/Startup.cs +++ b/Retroactiune.WebAPI/Startup.cs @@ -32,7 +32,7 @@ namespace Retroactiune // Services - services.AddSingleton(); + services.AddSingleton(); // WebAPI services.AddControllers(); diff --git a/Retroactiune.sln b/Retroactiune.sln index f61628e..5e9c021 100644 --- a/Retroactiune.sln +++ b/Retroactiune.sln @@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Retroactiune.WebAPI", "Retroactiune.WebAPI\Retroactiune.WebAPI.csproj", "{A40A0DBB-42D4-4619-9B80-120517561DF1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Retroactiune.Tests", "Retroactiune.Tests\Retroactiune.Tests.csproj", "{08AE3560-A324-4843-90DB-17DFC54600B5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Retroactiune.Tests", "Retroactiune.Tests\Retroactiune.Tests.csproj", "{2A2B5780-B8EF-4260-9EC1-3A2BFE5CDA7F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -14,9 +14,9 @@ Global {A40A0DBB-42D4-4619-9B80-120517561DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {A40A0DBB-42D4-4619-9B80-120517561DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {A40A0DBB-42D4-4619-9B80-120517561DF1}.Release|Any CPU.Build.0 = Release|Any CPU - {08AE3560-A324-4843-90DB-17DFC54600B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {08AE3560-A324-4843-90DB-17DFC54600B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08AE3560-A324-4843-90DB-17DFC54600B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {08AE3560-A324-4843-90DB-17DFC54600B5}.Release|Any CPU.Build.0 = Release|Any CPU + {2A2B5780-B8EF-4260-9EC1-3A2BFE5CDA7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A2B5780-B8EF-4260-9EC1-3A2BFE5CDA7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A2B5780-B8EF-4260-9EC1-3A2BFE5CDA7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A2B5780-B8EF-4260-9EC1-3A2BFE5CDA7F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal