public async Task UpdateTodoAsync(UpdatedTodoDTO updatedTodoDTO) { var todoToUpdate = _mapper.Map <UpdatedTodoDTO, Todo>(updatedTodoDTO); try { await _todosRepository.UpdateTodoAsync(todoToUpdate); } catch (RecordNotFoundException) { throw new TodoNotFoundException(); } catch (ConcurrentAccessException) { // TODO: Add logging here to indicate that we have hit // a database concurrency issue. For now I'll just // throw a NotFound error if the todo does not actually exist. // If it does exist, for now I'll just rethrow the error. bool todoExists = await _todosRepository.Exists(updatedTodoDTO.Id.Value); if (!todoExists) { throw new TodoNotFoundException(); } throw; } }
public async Task <ActionResult> UpdateTodo(long id, UpdatedTodoDTO updatedTodoDTO) { if (updatedTodoDTO == null) { return(BadRequest("No todo found in payload")); } if (!ModelState.IsValid) { return(BadRequest(ModelState)); } if (id != updatedTodoDTO.Id) { // TODO: Best to return an object and not a string, but for now // I'll at least do this. return(BadRequest("The id in the route does not match the id in your payload")); } try { await _todosService.UpdateTodoAsync(updatedTodoDTO); return(NoContent()); } catch (TodoNotFoundException) { return(NotFound()); } }
public async Task UpdateTodoAsync_MakesCorrectCalls() { // Arrange var todoDTO = new UpdatedTodoDTO() { Id = 1, Name = "Updated Todo", IsComplete = true }; var todo = new Todo() { Id = 1, Name = "Updated Todo", IsComplete = true }; var mockedMapper = new Mock <IMapper>(); var mockedRepository = new Mock <ITodosRepository>(); mockedMapper.Setup(m => m.Map <UpdatedTodoDTO, Todo>(todoDTO)).Returns(todo); mockedRepository.Setup(r => r.UpdateTodoAsync(todo)); var service = new TodosService(mockedMapper.Object, mockedRepository.Object); // Action await service.UpdateTodoAsync(todoDTO); // Assert mockedMapper.Verify(m => m.Map <UpdatedTodoDTO, Todo>(todoDTO), Times.Once()); mockedRepository.Verify(r => r.UpdateTodoAsync(todo), Times.Once()); }
public async Task UpdateTodoAsync_RecordNotFoundExceptionThrown_ThrowsTodoNotFoundException() { // Arrange var todoDTO = new UpdatedTodoDTO(); var mockedMapper = new Mock <IMapper>(); var mockedRepository = new Mock <ITodosRepository>(); mockedRepository.Setup(r => r.UpdateTodoAsync(It.IsAny <Todo>())).Throws <RecordNotFoundException>(); var service = new TodosService(mockedMapper.Object, mockedRepository.Object); // Action and Assert await Assert.ThrowsAsync <TodoNotFoundException>(async() => { await service.UpdateTodoAsync(todoDTO); }); }
public void UpdatedTodoDTO_IdIsMissing_GeneratesModelStateError() { // Arrange var results = new List <ValidationResult>(); var createdTodo = new UpdatedTodoDTO() { Name = "Hello World", IsComplete = true }; var isValid = Validator.TryValidateObject(createdTodo, new ValidationContext(createdTodo), results, true); Assert.False(isValid); Assert.Single(results); Assert.Equal("The Id field of the Todo is required.", results[0].ErrorMessage); }
public void UpdatedTodoDTO_NameIsBetween1And255Characters_NoModelStateError() { // Arrange var name = "".PadLeft(100, '*'); var results = new List <ValidationResult>(); var createdTodo = new UpdatedTodoDTO() { Id = 1, Name = name, IsComplete = true }; var isValid = Validator.TryValidateObject(createdTodo, new ValidationContext(createdTodo), results, true); Assert.True(isValid); Assert.Empty(results); }
public void UpdatedTodoDTO_NameIsTooLong_GeneratesModelStateError() { // Arrange var name = "".PadLeft(256, '*'); var results = new List <ValidationResult>(); var createdTodo = new UpdatedTodoDTO() { Id = 1, Name = name, IsComplete = true }; var isValid = Validator.TryValidateObject(createdTodo, new ValidationContext(createdTodo), results, true); Assert.False(isValid); Assert.Single(results); Assert.Equal("The Name field must be between 1 and 255 characters.", results[0].ErrorMessage); }
public async Task UpdateTodoAsync_ConcurrentAccessExceptionAndItemDoesNotExist_ThrowsTodoNotFoundException() { // Arrange var todoDTO = new UpdatedTodoDTO() { Id = 1 }; var mockedMapper = new Mock <IMapper>(); var mockedRepository = new Mock <ITodosRepository>(); mockedRepository.Setup(r => r.UpdateTodoAsync(It.IsAny <Todo>())).Throws <ConcurrentAccessException>(); mockedRepository.Setup(r => r.Exists(It.IsAny <long>())).ReturnsAsync(false); var service = new TodosService(mockedMapper.Object, mockedRepository.Object); // Action and Assert await Assert.ThrowsAsync <TodoNotFoundException>(async() => { await service.UpdateTodoAsync(todoDTO); }); }
public async Task UpdateTodo_IdOnRouteDoesNotMatchPayload_ReturnsBadRequest() { // Arrange var todoId = 1; var updatedTodoDTO = new UpdatedTodoDTO() { Id = 2, Name = "Todo 1", IsComplete = true }; var mockService = new Mock <ITodosService>(); var controller = new TodosController(mockService.Object); // Action var result = await controller.UpdateTodo(todoId, updatedTodoDTO); // Assert Assert.NotNull(result); Assert.IsType <BadRequestObjectResult>(result); }
public async Task UpdateTodo_ModelStateError_ReturnsBadRequest() { // Arrange var todoId = 1; var updatedTodoDTO = new UpdatedTodoDTO() { Name = "Todo 1", IsComplete = true }; var mockService = new Mock <ITodosService>(); var controller = new TodosController(mockService.Object); // Action controller.ModelState.AddModelError("updatedTodoDTO.Id", "ModelState error"); var result = await controller.UpdateTodo(todoId, updatedTodoDTO); // Assert Assert.NotNull(result); Assert.IsType <BadRequestObjectResult>(result); }
public async Task UpdateTodo_ValidTodoToUpdate_ReturnsNoContentResult() { // Arrange var todoId = 1; var updatedTodoDTO = new UpdatedTodoDTO() { Id = todoId, Name = "Todo 1", IsComplete = true }; var mockService = new Mock <ITodosService>(); mockService.Setup(ts => ts.UpdateTodoAsync(updatedTodoDTO)); var controller = new TodosController(mockService.Object); // Action var result = await controller.UpdateTodo(todoId, updatedTodoDTO); // Assert Assert.NotNull(result); Assert.IsType <NoContentResult>(result); mockService.Verify(ts => ts.UpdateTodoAsync(updatedTodoDTO), Times.Once()); }