using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using GermanApp.Application.DTOs; using GermanApp.Application.Services; using GermanApp.Domain.Entities; using GermanApp.Domain.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; namespace GermanApp.Tests.Unit.Application.Services; [TestClass] public class QuizQuestionServiceTests { private Mock _mockQuizQuestionRepo; private Mock _mockQuizOptionRepo; private Mock _mockLessonRepo; private QuizQuestionService _service; [TestInitialize] public void Setup() { _mockQuizQuestionRepo = new Mock(); _mockQuizOptionRepo = new Mock(); _mockLessonRepo = new Mock(); _service = new QuizQuestionService( _mockQuizQuestionRepo.Object, _mockQuizOptionRepo.Object, _mockLessonRepo.Object); } [TestMethod] public async Task GetAllQuizQuestionsAsync_ReturnsMappedDtoList() { var lesson = Lesson.Create(1, "Test Lesson", 1, "Test Topic", "Test Description"); var questions = new List { QuizQuestion.Create(1, "Question 1", QuestionType.MultipleChoice, "Answer 1", 3, 1) }; _mockQuizQuestionRepo.Setup(r => r.GetAllOrderedAsync(It.IsAny())) .ReturnsAsync(questions); var result = await _service.GetAllQuizQuestionsAsync(); Assert.AreEqual(1, result.Count); Assert.AreEqual("Question 1", result[0].QuestionText); } [TestMethod] public async Task GetQuizQuestionByIdAsync_WithExistingId_ReturnsQuestion() { var question = QuizQuestion.Create(1, "Test Question", QuestionType.MultipleChoice, "Test Answer", 3, 1); _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(question); var result = await _service.GetQuizQuestionByIdAsync(1); Assert.IsNotNull(result); Assert.AreEqual("Test Question", result.QuestionText); } [TestMethod] public async Task GetQuizQuestionByIdAsync_WithNonExistingId_ReturnsNull() { _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(999, It.IsAny())) .ReturnsAsync((QuizQuestion?)null); var result = await _service.GetQuizQuestionByIdAsync(999); Assert.IsNull(result); } [TestMethod] public async Task GetQuizQuestionsByLessonAsync_ReturnsFilteredQuestions() { var questions = new List { QuizQuestion.Create(1, "Q1", QuestionType.MultipleChoice, "A1", 3, 1) }; _mockQuizQuestionRepo.Setup(r => r.GetByLessonAsync(1, It.IsAny())) .ReturnsAsync(questions); var result = await _service.GetQuizQuestionsByLessonAsync(1); Assert.AreEqual(1, result.Count); Assert.AreEqual("Q1", result[0].QuestionText); } [TestMethod] public async Task GetActiveQuizQuestionsByLessonAsync_ReturnsOnlyActive() { var activeQuestion = QuizQuestion.Create(1, "Active", QuestionType.MultipleChoice, "A1", 3, 1); var inactiveQuestion = QuizQuestion.Create(1, "Inactive", QuestionType.MultipleChoice, "A2", 3, 2); inactiveQuestion.Deactivate(); var questions = new List { activeQuestion, inactiveQuestion }; _mockQuizQuestionRepo.Setup(r => r.GetActiveByLessonAsync(1, It.IsAny())) .ReturnsAsync(new List { activeQuestion }); var result = await _service.GetActiveQuizQuestionsByLessonAsync(1); Assert.AreEqual(1, result.Count); Assert.AreEqual("Active", result[0].QuestionText); } [TestMethod] public async Task CreateQuizQuestionAsync_WithValidDtoAndValidLesson_CreatesQuestion() { var lesson = Lesson.Create(1, "Test Lesson", 1, "Test Topic", "Test Description"); var options = new List { new CreateQuizOptionDto("Option 1", true, 1), new CreateQuizOptionDto("Option 2", false, 2) }; var dto = new CreateQuizQuestionDto( 1, "New Question", QuestionType.MultipleChoice, "Answer 1", 3, 1, options); var createdQuestion = QuizQuestion.Create(1, "New Question", QuestionType.MultipleChoice, "Answer 1", 3, 1); _mockLessonRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(lesson); _mockQuizQuestionRepo.Setup(r => r.OrderExistsInLessonAsync(1, 1, null, It.IsAny())) .ReturnsAsync(false); _mockQuizQuestionRepo.Setup(r => r.AddAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(createdQuestion); _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(createdQuestion.Id, It.IsAny())) .ReturnsAsync(createdQuestion); var result = await _service.CreateQuizQuestionAsync(dto); Assert.IsNotNull(result); Assert.AreEqual("New Question", result.QuestionText); } [TestMethod] public async Task UpdateQuizQuestionAsync_WithExistingQuestion_UpdatesQuestion() { var lesson = Lesson.Create(1, "Test Lesson", 1, "Test Topic", "Test Description"); var existing = QuizQuestion.Create(1, "Old Question", QuestionType.MultipleChoice, "Old Answer", 3, 1); var options = new List { new UpdateQuizOptionDto(1, "Updated Option", true, 1) }; var dto = new UpdateQuizQuestionDto(1, "Updated Question", QuestionType.TrueFalse, "New Answer", 4, 1, true, options); _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(existing); _mockLessonRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(lesson); _mockQuizQuestionRepo.Setup(r => r.OrderExistsInLessonAsync(1, 1, 1, It.IsAny())) .ReturnsAsync(false); _mockQuizQuestionRepo.Setup(r => r.UpdateAsync(existing, It.IsAny())) .Returns(Task.CompletedTask); _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(existing); _mockQuizOptionRepo.Setup(r => r.DeleteByQuestionAsync(1, It.IsAny())) .Returns(Task.CompletedTask); var result = await _service.UpdateQuizQuestionAsync(1, dto); Assert.IsNotNull(result); Assert.AreEqual("Updated Question", result.QuestionText); } [TestMethod] public async Task DeleteQuizQuestionAsync_WithExistingQuestion_ReturnsTrue() { var question = QuizQuestion.Create(1, "Test Question", QuestionType.MultipleChoice, "Answer", 3, 1); _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(question); _mockQuizOptionRepo.Setup(r => r.DeleteByQuestionAsync(1, It.IsAny())) .Returns(Task.CompletedTask); _mockQuizQuestionRepo.Setup(r => r.DeleteAsync(question, It.IsAny())) .Returns(Task.CompletedTask); var result = await _service.DeleteQuizQuestionAsync(1); Assert.IsTrue(result); } [TestMethod] public async Task GetQuizOptionsByQuestionAsync_ReturnsOptions() { var options = new List { QuizOption.Create(1, "Option 1", true, 1), QuizOption.Create(1, "Option 2", false, 2) }; _mockQuizOptionRepo.Setup(r => r.GetByQuestionAsync(1, It.IsAny())) .ReturnsAsync(options); var result = await _service.GetQuizOptionsByQuestionAsync(1); Assert.AreEqual(2, result.Count); } [TestMethod] public async Task GetCorrectOptionAsync_ReturnsCorrectOption() { var option = QuizOption.Create(1, "Correct Option", true, 1); _mockQuizOptionRepo.Setup(r => r.GetCorrectOptionAsync(1, It.IsAny())) .ReturnsAsync(option); var result = await _service.GetCorrectOptionAsync(1); Assert.IsNotNull(result); Assert.IsTrue(result.IsCorrect); } [TestMethod] public async Task CreateQuizOptionAsync_WithValidData_CreatesOption() { var question = QuizQuestion.Create(1, "Test Question", QuestionType.MultipleChoice, "Answer", 3, 1); var dto = new CreateQuizOptionDto("New Option", true, 1); var createdOption = QuizOption.Create(1, "New Option", true, 1); _mockQuizQuestionRepo.Setup(r => r.GetByIdAsync(1, It.IsAny())) .ReturnsAsync(question); _mockQuizOptionRepo.Setup(r => r.OrderExistsForQuestionAsync(1, 1, null, It.IsAny())) .ReturnsAsync(false); _mockQuizOptionRepo.Setup(r => r.AddAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(createdOption); var result = await _service.CreateQuizOptionAsync(1, dto); Assert.IsNotNull(result); Assert.AreEqual("New Option", result.Text); } [TestMethod] public async Task SubmitQuizAnswersAsync_WithCorrectAnswers_ReturnsPassedResult() { var question = QuizQuestion.Create(1, "What is 2+2?", QuestionType.FillInTheBlank, "4", 3, 1); var questions = new List { question }; var answers = new List { new QuizAnswerDto(1, "4", null) }; var dto = new SubmitQuizAnswersDto(1, answers); _mockQuizQuestionRepo.Setup(r => r.GetByLessonAsync(1, It.IsAny())) .ReturnsAsync(questions); var result = await _service.SubmitQuizAnswersAsync(1, dto); Assert.AreEqual(1, result.TotalQuestions); Assert.AreEqual(1, result.CorrectAnswers); Assert.AreEqual(100, result.ScorePercentage); Assert.IsTrue(result.Passed); } [TestMethod] public async Task SubmitQuizAnswersAsync_WithIncorrectAnswers_ReturnsFailedResult() { var question = QuizQuestion.Create(1, "What is 2+2?", QuestionType.FillInTheBlank, "4", 3, 1); var questions = new List { question }; var answers = new List { new QuizAnswerDto(1, "5", null) // Wrong answer }; var dto = new SubmitQuizAnswersDto(1, answers); _mockQuizQuestionRepo.Setup(r => r.GetByLessonAsync(1, It.IsAny())) .ReturnsAsync(questions); var result = await _service.SubmitQuizAnswersAsync(1, dto); Assert.AreEqual(1, result.TotalQuestions); Assert.AreEqual(0, result.CorrectAnswers); Assert.AreEqual(0, result.ScorePercentage); Assert.IsFalse(result.Passed); } [TestMethod] public async Task GetQuizQuestionCountForLessonAsync_ReturnsCount() { var questions = new List { QuizQuestion.Create(1, "Q1", QuestionType.MultipleChoice, "A1", 3, 1), QuizQuestion.Create(1, "Q2", QuestionType.MultipleChoice, "A2", 3, 2) }; _mockQuizQuestionRepo.Setup(r => r.GetActiveByLessonAsync(1, It.IsAny())) .ReturnsAsync(questions); var result = await _service.GetQuizQuestionCountForLessonAsync(1); Assert.AreEqual(2, result); } [TestMethod] public async Task GetDifficultyDistributionAsync_ReturnsDistribution() { var questions = new List { QuizQuestion.Create(1, "Easy", QuestionType.MultipleChoice, "A1", 1, 1), QuizQuestion.Create(1, "Medium", QuestionType.MultipleChoice, "A2", 3, 2), QuizQuestion.Create(1, "Hard", QuestionType.MultipleChoice, "A3", 5, 3) }; _mockQuizQuestionRepo.Setup(r => r.GetActiveByLessonAsync(1, It.IsAny())) .ReturnsAsync(questions); var result = await _service.GetDifficultyDistributionAsync(1); Assert.AreEqual(1, result[1]); // Easy Assert.AreEqual(0, result[2]); // No questions with difficulty 2 Assert.AreEqual(1, result[3]); // Medium Assert.AreEqual(0, result[4]); // No questions with difficulty 4 Assert.AreEqual(1, result[5]); // Hard } }