using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GermanApp.Application.DTOs;
using GermanApp.Application.Services;
using GermanApp.Presentation.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace GermanApp.Tests.Integration.Controllers;
///
/// Integration tests for LevelsController.
/// Tests controller behavior with mocked services.
///
[TestClass]
public class LevelsControllerTests
{
private Mock? _mockLevelService;
private LevelsController? _controller;
[TestInitialize]
public void TestInitialize()
{
_mockLevelService = new Mock(null!);
_controller = new LevelsController(_mockLevelService.Object);
}
[TestCleanup]
public void TestCleanup()
{
_controller = null;
_mockLevelService = null;
}
// ==================== GET ALL LEVELS TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetAllLevels")]
public async Task GetAllLevels_WithData_ReturnsOkWithLevels()
{
// Arrange
var expectedLevels = new List
{
new LevelDto(1, "Beginner A1", "A1", 1),
new LevelDto(2, "Elementary A2", "A2", 2)
};
_mockLevelService!.Setup(s => s.GetAllLevelsAsync(It.IsAny()))
.ReturnsAsync(expectedLevels);
// Act
var result = await _controller!.GetAllLevelsAsync();
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevels = okResult.Value as IReadOnlyList;
Assert.IsNotNull(returnedLevels);
Assert.AreEqual(2, returnedLevels.Count);
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetAllLevels")]
public async Task GetAllLevels_WithNoData_ReturnsEmptyList()
{
// Arrange
var expectedLevels = new List();
_mockLevelService!.Setup(s => s.GetAllLevelsAsync(It.IsAny()))
.ReturnsAsync(expectedLevels);
// Act
var result = await _controller!.GetAllLevelsAsync();
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevels = okResult.Value as IReadOnlyList;
Assert.IsNotNull(returnedLevels);
Assert.AreEqual(0, returnedLevels.Count);
}
// ==================== GET LEVEL BY ID TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetLevelById")]
public async Task GetLevelById_WithExistingId_ReturnsOkWithLevel()
{
// Arrange
var expectedLevel = new LevelDto(1, "Beginner A1", "A1", 1);
_mockLevelService!.Setup(s => s.GetLevelByIdAsync(1, It.IsAny()))
.ReturnsAsync(expectedLevel);
// Act
var result = await _controller!.GetLevelByIdAsync(1);
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevel = okResult.Value as LevelDto;
Assert.IsNotNull(returnedLevel);
Assert.AreEqual(1, returnedLevel.Id);
Assert.AreEqual("Beginner A1", returnedLevel.Name);
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetLevelById")]
public async Task GetLevelById_WithNonExistingId_ReturnsNotFound()
{
// Arrange
_mockLevelService!.Setup(s => s.GetLevelByIdAsync(999, It.IsAny()))
.ReturnsAsync((LevelDto?)null);
// Act
var result = await _controller!.GetLevelByIdAsync(999);
// Assert
Assert.IsInstanceOfType(result, typeof(NotFoundResult));
}
// ==================== GET LEVEL BY CODE TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetLevelByCode")]
public async Task GetLevelByCode_WithExistingCode_ReturnsOkWithLevel()
{
// Arrange
var expectedLevel = new LevelDto(1, "Beginner A1", "A1", 1);
_mockLevelService!.Setup(s => s.GetLevelByCodeAsync("A1", It.IsAny()))
.ReturnsAsync(expectedLevel);
// Act
var result = await _controller!.GetLevelByCodeAsync("A1");
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevel = okResult.Value as LevelDto;
Assert.IsNotNull(returnedLevel);
Assert.AreEqual("A1", returnedLevel.Code);
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetLevelByCode")]
public async Task GetLevelByCode_WithNonExistingCode_ReturnsNotFound()
{
// Arrange
_mockLevelService!.Setup(s => s.GetLevelByCodeAsync("INVALID", It.IsAny()))
.ReturnsAsync((LevelDto?)null);
// Act
var result = await _controller!.GetLevelByCodeAsync("INVALID");
// Assert
Assert.IsInstanceOfType(result, typeof(NotFoundResult));
}
// ==================== CREATE LEVEL TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("CreateLevel")]
public async Task CreateLevel_WithValidData_ReturnsCreatedAtAction()
{
// Arrange
var createDto = new CreateLevelDto("Beginner A1", "A1", 1);
var expectedLevel = new LevelDto(1, "Beginner A1", "A1", 1);
_mockLevelService!.Setup(s => s.CreateLevelAsync(createDto, It.IsAny()))
.ReturnsAsync(expectedLevel);
// Act
var result = await _controller!.CreateLevelAsync(createDto);
// Assert
Assert.IsInstanceOfType(result, typeof(CreatedAtActionResult));
var createdResult = result as CreatedAtActionResult;
Assert.IsNotNull(createdResult);
var returnedLevel = createdResult.Value as LevelDto;
Assert.IsNotNull(returnedLevel);
Assert.AreEqual(1, returnedLevel.Id);
}
// ==================== UPDATE LEVEL TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("UpdateLevel")]
public async Task UpdateLevel_WithExistingId_ReturnsOkWithUpdatedLevel()
{
// Arrange
var updateDto = new UpdateLevelDto("Updated A1", "A1", 1);
var expectedLevel = new LevelDto(1, "Updated A1", "A1", 1);
_mockLevelService!.Setup(s => s.UpdateLevelAsync(1, updateDto, It.IsAny()))
.ReturnsAsync(expectedLevel);
// Act
var result = await _controller!.UpdateLevelAsync(1, updateDto);
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevel = okResult.Value as LevelDto;
Assert.IsNotNull(returnedLevel);
Assert.AreEqual("Updated A1", returnedLevel.Name);
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("UpdateLevel")]
public async Task UpdateLevel_WithNonExistingId_ReturnsNotFound()
{
// Arrange
var updateDto = new UpdateLevelDto("Updated A1", "A1", 1);
_mockLevelService!.Setup(s => s.UpdateLevelAsync(999, updateDto, It.IsAny()))
.ReturnsAsync((LevelDto?)null);
// Act
var result = await _controller!.UpdateLevelAsync(999, updateDto);
// Assert
Assert.IsInstanceOfType(result, typeof(NotFoundResult));
}
// ==================== DELETE LEVEL TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("DeleteLevel")]
public async Task DeleteLevel_WithExistingId_ReturnsNoContent()
{
// Arrange
_mockLevelService!.Setup(s => s.DeleteLevelAsync(1, It.IsAny()))
.ReturnsAsync(true);
// Act
var result = await _controller!.DeleteLevelAsync(1);
// Assert
Assert.IsInstanceOfType(result, typeof(NoContentResult));
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("DeleteLevel")]
public async Task DeleteLevel_WithNonExistingId_ReturnsNotFound()
{
// Arrange
_mockLevelService!.Setup(s => s.DeleteLevelAsync(999, It.IsAny()))
.ReturnsAsync(false);
// Act
var result = await _controller!.DeleteLevelAsync(999);
// Assert
Assert.IsInstanceOfType(result, typeof(NotFoundResult));
}
// ==================== GET FIRST LEVEL TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetFirstLevel")]
public async Task GetFirstLevel_WithData_ReturnsOkWithLevel()
{
// Arrange
var expectedLevel = new LevelDto(1, "Beginner A1", "A1", 1);
_mockLevelService!.Setup(s => s.GetFirstLevelAsync(It.IsAny()))
.ReturnsAsync(expectedLevel);
// Act
var result = await _controller!.GetFirstLevelAsync();
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevel = okResult.Value as LevelDto;
Assert.IsNotNull(returnedLevel);
Assert.AreEqual(1, returnedLevel.Order);
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetFirstLevel")]
public async Task GetFirstLevel_WithNoData_ReturnsNotFound()
{
// Arrange
_mockLevelService!.Setup(s => s.GetFirstLevelAsync(It.IsAny()))
.ReturnsAsync((LevelDto?)null);
// Act
var result = await _controller!.GetFirstLevelAsync();
// Assert
Assert.IsInstanceOfType(result, typeof(NotFoundResult));
}
// ==================== GET NEXT LEVEL TESTS ====================
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetNextLevel")]
public async Task GetNextLevel_WithExistingCurrentLevel_ReturnsOkWithNextLevel()
{
// Arrange
var expectedLevel = new LevelDto(2, "Elementary A2", "A2", 2);
_mockLevelService!.Setup(s => s.GetNextLevelAsync(1, It.IsAny()))
.ReturnsAsync(expectedLevel);
// Act
var result = await _controller!.GetNextLevelAsync(1);
// Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = result as OkObjectResult;
Assert.IsNotNull(okResult);
var returnedLevel = okResult.Value as LevelDto;
Assert.IsNotNull(returnedLevel);
Assert.AreEqual(2, returnedLevel.Order);
}
[TestMethod]
[TestCategory("LevelsController")]
[TestCategory("GetNextLevel")]
public async Task GetNextLevel_WithNoNextLevel_ReturnsNotFound()
{
// Arrange
_mockLevelService!.Setup(s => s.GetNextLevelAsync(5, It.IsAny()))
.ReturnsAsync((LevelDto?)null);
// Act
var result = await _controller!.GetNextLevelAsync(5);
// Assert
Assert.IsInstanceOfType(result, typeof(NotFoundResult));
}
}