public async Task GetQuestionAsync_Exists_ReturnQuestion()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddQuestionCategory("Class1", "Category1")
				.AddQuestion
				(
					"Class1", 
					"Category1", 
					new MethodQuestion() { Name = "Question1" }
				).Build();

			var questionId = database.Context.Questions.First().Id;

			database.Reload();

			var loaderFactory = GetMockQuestionLoaderFactory();
			var questionService = CreateQuestionService
			(
				database.Context, 
				questionLoaderFactory: loaderFactory.Object
			);

			var question = await questionService.GetQuestionAsync
			(
				"Class1",
				questionId
			);

			loaderFactory.Verify(LoadQuestionExpression);
			Assert.Equal("Class1", question.QuestionCategory.Classroom.Name);
			Assert.Equal("Category1", question.QuestionCategory.Name);
			Assert.Equal("Question1", question.Name);
		}
		public async Task GetQuestionsAsync_OnlyForClassroom()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.AddQuestionCategory("Class1", "Category1")
				.AddQuestionCategory("Class1", "Category2")
				.AddQuestionCategory("Class2", "Category1")
				.AddQuestion("Class1", "Category1", new MethodQuestion() { Name = "Question1" })
				.AddQuestion("Class1", "Category2", new ClassQuestion() { Name = "Question2" })
				.AddQuestion("Class2", "Category1", new ClassQuestion() { Name = "Question3" })
				.Build();

			var questionService = CreateQuestionService(database.Context);
			var questions = await questionService.GetQuestionsAsync("Class1");
			var orderedQuestions = questions.OrderBy(q => q.QuestionCategory.Name)
				.ToList();

			Assert.Equal(2, orderedQuestions.Count);
			Assert.Equal("Class1", orderedQuestions[0].QuestionCategory.Classroom.Name);
			Assert.Equal("Category1", orderedQuestions[0].QuestionCategory.Name);
			Assert.Equal("Question1", orderedQuestions[0].Name);
			Assert.Equal("Class1", orderedQuestions[1].QuestionCategory.Classroom.Name);
			Assert.Equal("Category2", orderedQuestions[1].QuestionCategory.Name);
			Assert.Equal("Question2", orderedQuestions[1].Name);
		}
		public async Task GetSectionAsync_DoesntExist_ReturnNull()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();

			var sectionService = new SectionService(database.Context);
			var section = await sectionService.GetSectionAsync("Class1", "Section1");

			Assert.Null(section);
		}
		public async Task GetClassroomAsync_DoesntExist_ReturnNull()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();

			var classroomService = new ClassroomService(database.Context);
			var classroom = await classroomService.GetClassroomAsync("Class2");

			Assert.Null(classroom);
		}
		public async Task GetProjectAsync_DoesntExist_ReturnNull()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();

			var projectService = GetProjectService(database.Context);
			var project = await projectService.GetProjectAsync("Class1", "Project1");

			Assert.Null(project);
		}
		public async Task GetClassroomsAsync_ReturnsAllClassrooms()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.Build();

			var classroomService = new ClassroomService(database.Context);
			var classrooms = await classroomService.GetClassroomsAsync();

			Assert.Equal(2, classrooms.Count);
			Assert.Equal("Class1", classrooms[0].Name);
			Assert.Equal("Class1", classrooms[0].Name);
		}
		public async Task GetQuestionCategoryAsync_DoesntExist_ReturnNull()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();
			
			var questionCategoryService = new QuestionCategoryService(database.Context);
			var category = await questionCategoryService.GetQuestionCategoryAsync
			(
				"Class1",
				id: 1
			);

			Assert.Null(category);
		}
		public async Task GetSectionAsync_Exists_ReturnSection()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddSection("Class1", "Section1")
				.Build();

			database.Reload();

			var sectionService = new SectionService(database.Context);
			var section = await sectionService.GetSectionAsync("Class1", "Section1");

			Assert.Equal("Class1", section.Classroom.Name);
			Assert.Equal("Section1", section.Name);
		}
		public async Task GetClassroomAsync_Exists_ReturnsClassroom()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.Build();

			var classroomId = database.Context.Classrooms.First().Id;

			database.Reload();

			var classroomService = new ClassroomService(database.Context);
			var classroom = await classroomService.GetClassroomAsync("Class1");

			Assert.Equal("Class1", classroom.Name);
		}
		public async Task GetAndUpdateCurrentUserAsync_Unregistered_ReturnsNull()
		{
			var database = new TestDatabaseBuilder().Build();

			var identityProvider = GetMockIdentityProvider(GetIdentity("User1"));

			var userService = GetUserService
			(
				database.Context,
				identityProvider.Object
			);

			var currentUser = await userService.GetAndUpdateCurrentUserAsync();

			Assert.Null(currentUser);
		}
		public async Task GetCheckpointAsync_DoesntExist_ReturnNull()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddProject("Class1", "Project1")
				.Build();

			var checkpointService = GetCheckpointService(database.Context);
			var checkpoint = await checkpointService.GetCheckpointAsync
			(
				"Class1", 
				"Project1", 
				"Checkpoint1"
			);

			Assert.Null(checkpoint);
		}
		public async Task GetProjectsAsync_OnlyForClassroom()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.AddProject("Class1", "Project1")
				.AddProject("Class1", "Project2")
				.AddProject("Class2", "Project3")
				.Build();

			var projectService = GetProjectService(database.Context);
			var projects = await projectService.GetProjectsAsync("Class1");

			Assert.Equal(2, projects.Count);
			Assert.Equal("Project1", projects[0].Name);
			Assert.Equal("Project2", projects[1].Name);
		}
		public async Task GetQuestionCategoriesAsync_OnlyForClassroom()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.AddQuestionCategory("Class1", "Category1")
				.AddQuestionCategory("Class1", "Category2")
				.AddQuestionCategory("Class2", "Category1")
				.Build();

			var questionCategoryService = new QuestionCategoryService(database.Context);
			var categories = await questionCategoryService.GetQuestionCategoriesAsync("Class1");

			Assert.Equal(2, categories.Count);
			Assert.Equal("Class1", categories[0].Classroom.Name);
			Assert.Equal("Category1", categories[0].Name);
			Assert.Equal("Class1", categories[0].Classroom.Name);
			Assert.Equal("Category2", categories[1].Name);
		}
		public async Task GetSectionMembershipsAsync_ReturnStudents()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddSection("Class1", "Section1")
				.AddSection("Class1", "Section2")
				.AddStudent("User1", "Last", "First", "Class1", "Section1")
				.AddStudent("User2", "Last", "First", "Class1", "Section1")
				.AddStudent("User3", "Last", "First", "Class1", "Section2")
				.Build();

			database.Reload();

			var sectionService = new SectionService(database.Context);
			var students = await sectionService.GetSectionStudentsAsync("Class1", "Section1");

			Assert.Equal(2, students.Count);
			Assert.Equal("User1", students[0].ClassroomMembership.User.UserName);
			Assert.Equal("User2", students[1].ClassroomMembership.User.UserName);
		}
		public async Task GetCheckpointsAsync_OnlyForProject()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddProject("Class1", "Project1")
				.AddProject("Class1", "Project2")
				.AddCheckpoint("Class1", "Project1", "Checkpoint1")
				.AddCheckpoint("Class1", "Project1", "Checkpoint2")
				.AddCheckpoint("Class1", "Project2", "Checkpoint1")
				.Build();

			var checkpointService = GetCheckpointService(database.Context);
			var checkpoints = await checkpointService.GetCheckpointsAsync("Class1", "Project1");

			Assert.Equal(2, checkpoints.Count);
			Assert.Equal("Project1", checkpoints[0].Project.Name);
			Assert.Equal("Checkpoint1", checkpoints[0].Name);
			Assert.Equal("Project1", checkpoints[1].Project.Name);
			Assert.Equal("Checkpoint2", checkpoints[1].Name);
		}
		public async Task GetQuestionCategoryAsync_Exists_ReturnCategory()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddQuestionCategory("Class1", "Category1")
				.Build();

			var questionCategoryId = database.Context.QuestionCategories.First().Id;

			database.Reload();

			var questionCategoryService = new QuestionCategoryService(database.Context);
			var category = await questionCategoryService.GetQuestionCategoryAsync
			(
				"Class1", 
				questionCategoryId
			);

			Assert.Equal("Class1", category.Classroom.Name);
			Assert.Equal("Category1", category.Name);
		}
		public async Task GetAndUpdateCurrentUserAsync_Registered_ReturnsUser()
		{
			var database = new TestDatabaseBuilder()
			   .AddClassroom("Class1")
			   .AddSection("Class1", "Section1")
			   .AddStudent("User1", "LastName", "FirstName", "Class1", "Section1")
			   .Build();

			var identityProvider = GetMockIdentityProvider(GetIdentity("User1"));

			var userService = GetUserService
			(
				database.Context,
				identityProvider.Object
			);

			var currentUser = await userService.GetAndUpdateCurrentUserAsync();
			var classroomMembership = currentUser.ClassroomMemberships.Single();
			var sectionMembership = classroomMembership.SectionMemberships.Single();

			Assert.Equal("User1", currentUser.UserName);
			Assert.Equal("Class1", classroomMembership.Classroom.Name);
			Assert.Equal("Section1", sectionMembership.Section.Name);
		}
		public async Task CreateSectionAsync_SectionCreated()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();

			var sectionService = new SectionService(database.Context);
			await sectionService.CreateSectionAsync
			(
				"Class1",
				new Section()
				{
					Name = "Section1"
				}
			);

			database.Reload();

			var section = database.Context.Sections
				.Include(qc => qc.Classroom)
				.Single();

			Assert.Equal("Class1", section.Classroom.Name);
			Assert.Equal("Section1", section.Name);
		}
		public async Task GradeSubmissionAsync_NormalQuestion_StoresAndReturnsResult()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddSection("Class1", "Section1")
				.AddStudent("User1", "Last", "First", "Class1", "Section1")
				.AddQuestionCategory("Class1", "Category1")
				.AddQuestion("Class1", "Category1", new MethodQuestion() { Name = "Question1" })
				.Build();

			var questionId = database.Context.Questions.First().Id;
			var userId = database.Context.Users.First().Id;

			database.Reload();

			var loaderFactory = GetMockQuestionLoaderFactory();
			var graderFactory = GetMockQuestionGraderFactory();
			var timeProvider = GetMockTimeProvider(new DateTime(2016, 1, 1));
			var questionSubmission = new CodeQuestionSubmission()
			{
				Contents = "SubmissionContents"
			};

			var serializer = new Mock<IJsonSerializer>();
			serializer
				.Setup(s => s.Serialize<QuestionSubmission>(questionSubmission))
				.Returns("SerializedSubmissionContents");

			var questionService = CreateQuestionService
			(
				database.Context,
				questionLoaderFactory: loaderFactory.Object,
				questionGraderFactory: graderFactory.Object,
				jsonSerializer: serializer.Object,
				timeProvider: timeProvider.Object
			);

			var result = await questionService.GradeSubmissionAsync
			(
				"Class1",
				userId,
				questionId,
				questionSubmission
			);

			Assert.Equal(1.0, result.Score);

			database.Reload();

			var submission = database.Context
				.UserQuestionSubmissions
				.Where(uqs => uqs.UserQuestionData.UserId == userId)
				.Include(uqs => uqs.UserQuestionData)
				.Single(uqs => uqs.UserQuestionData.QuestionId == questionId);

			Assert.Equal(1.0, submission.Score);

			Assert.Equal
			(
				"SerializedSubmissionContents", 
				submission.UserQuestionData.LastQuestionSubmission
			);

			Assert.Equal
			(
				new DateTime(2016, 1, 1),
				submission.DateSubmitted
			);
		}
		public async Task DeleteQuestionCategoryAsync_CategoryDeleted()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddQuestionCategory("Class1", "Category1")
				.Build();
			
			var questionCategoryId = database.Context.QuestionCategories.First().Id;

			database.Reload();

			var questionCategoryService = new QuestionCategoryService(database.Context);
			await questionCategoryService.DeleteQuestionCategoryAsync
			(
				"Class1",
				questionCategoryId
			);

			database.Reload();
			
			Assert.Equal(0, database.Context.QuestionCategories.Count());
		}
		public async Task UpdateQuestionCategoryAsync_CategoryUpdated()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddQuestionCategory("Class1", "Category1", privateCategory: true)
				.Build();
			
			var questionCategory = database.Context.QuestionCategories
				.Include(qc => qc.Classroom)
				.First();

			// Update the category
			database.Context.Entry(questionCategory).State = EntityState.Detached;
			questionCategory.IsPrivate = false;

			// Apply the update
			var questionCategoryService = new QuestionCategoryService(database.Context);
			await questionCategoryService.UpdateQuestionCategoryAsync
			(
				"Class1",
				questionCategory
			);

			database.Reload();

			questionCategory = database.Context.QuestionCategories
				.Include(qc => qc.Classroom)
				.Single();

			Assert.Equal("Class1", questionCategory.Classroom.Name);
			Assert.Equal("Category1", questionCategory.Name);
			Assert.Equal(false, questionCategory.IsPrivate);
		}
		public async Task GetClassroomsWithAccessAsync_Student_ReturnsClassrooms()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddSection("Class1", "Section1")
				.AddClassroom("Class2")
				.AddSection("Class2", "Section2")
				.AddStudent("User1", "Last", "First", "Class2", "Section2")
				.Build();

			var userId = database.Context.Users.First().Id;
			var classroomId = database.Context.Classrooms
				.Single(c => c.Name == "Class2")
				.Id;

			database.Reload();

			var classroomService = new ClassroomService(database.Context);
			var classrooms = await classroomService.GetClassroomsWithAccessAsync(userId);

			Assert.Equal(1, classrooms.Count);
			Assert.Equal(userId, classrooms[0].UserId);
			Assert.Equal(classroomId, classrooms[0].ClassroomId);
		}
		public async Task UpdateSectionAsync_SectionUpdated()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddSection("Class1", "Section1")
				.Build();

			var section = database.Context.Sections
				.Include(qc => qc.Classroom)
				.First();

			// Update the section
			database.Context.Entry(section).State = EntityState.Detached;
			section.DisplayName = "New Display Name";

			// Apply the update
			var sectionService = new SectionService(database.Context);
			await sectionService.UpdateSectionAsync("Class1", section);

			database.Reload();

			section = database.Context.Sections
				.Include(qc => qc.Classroom)
				.Single();

			Assert.Equal("Class1", section.Classroom.Name);
			Assert.Equal("Section1", section.Name);
			Assert.Equal("New Display Name", section.DisplayName);
		}
		public async Task DeleteSectionAsync_SectionDeleted()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddSection("Class1", "Section1")
				.Build();
			
			database.Reload();

			var sectionService = new SectionService(database.Context);
			await sectionService.DeleteSectionAsync("Class1", "Section1");

			database.Reload();

			Assert.Equal(0, database.Context.Sections.Count());
		}
		public async Task DeleteClassroomAsync_ClassroomDeleted()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();

			var classroomId = database.Context.Classrooms.First().Id;

			database.Reload();

			var classroomService = new ClassroomService(database.Context);
			await classroomService.DeleteClassroomAsync("Class1");

			database.Reload();

			Assert.Equal(0, database.Context.Classrooms.Count());
		}
		public async Task UpdateClassroomAsync_ClassroomUpdated()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();

			var classroom = database.Context.Classrooms.Single();

			// Update the classroom
			database.Context.Entry(classroom).State = EntityState.Detached;
			classroom.DisplayName = "New Display Name";

			// Apply the update
			var classroomService = new ClassroomService(database.Context);
			await classroomService.UpdateClassroomAsync(classroom);

			database.Reload();

			classroom = database.Context.Classrooms.Single();

			Assert.Equal("Class1", classroom.Name);
			Assert.Equal("New Display Name", classroom.DisplayName);
		}
		public async Task CreateClassroomAsync_ClassroomCreated()
		{
			var database = new TestDatabaseBuilder().Build();

			var classroomService = new ClassroomService(database.Context);
			await classroomService.CreateClassroomAsync
			(
				new Classroom()
				{
					Name = "Class1"
				}
			);

			database.Reload();

			var classroom = database.Context.Classrooms.Single();

			Assert.Equal("Class1", classroom.Name);
		}
		public async Task GetClassroomAdminsAsync_ReturnsAdmins()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.AddAdmin("User1", "Last", "First", "Class1", superUser: false)
				.AddAdmin("User2", "Last", "First", "Class1", superUser: false)
				.AddAdmin("User3", "Last", "First", "Class2", superUser: false)
				.Build();

			var users = database.Context.Users
				.OrderBy(u => u.UserName)
				.ToList();

			database.Reload();

			var classroomService = new ClassroomService(database.Context);
			var admins = await classroomService.GetClassroomAdminsAsync("Class1");
			admins = admins.OrderBy(a => a.UserId).ToList();

			Assert.Equal(2, admins.Count);
			Assert.Equal(users[0].Id, admins[0].UserId);
			Assert.Equal(users[1].Id, admins[1].UserId);
		}
		public async Task CreateQuestionCategoryAsync_CategoryCreated()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.Build();
			
			var questionCategoryService = new QuestionCategoryService(database.Context);
			await questionCategoryService.CreateQuestionCategoryAsync
			(
				"Class1",
				new QuestionCategory()
				{
					Name = "Category1"
				}
			);

			database.Reload();

			var questionCategory = database.Context.QuestionCategories
				.Include(qc => qc.Classroom)
				.Single();

			Assert.Equal("Class1", questionCategory.Classroom.Name);
			Assert.Equal("Category1", questionCategory.Name);
		}
		public async Task GetClassroomsWithAccessAsync_SuperUser_ReturnsClassrooms()
		{
			var database = new TestDatabaseBuilder()
				.AddClassroom("Class1")
				.AddClassroom("Class2")
				.AddAdmin("User1", "Last", "First", "Class2", superUser: true)
				.Build();

			var userId = database.Context.Users.First().Id;
			var expectedClassrooms = database.Context.Classrooms
				.OrderBy(c => c.Id)
				.ToList();

			database.Reload();

			var classroomService = new ClassroomService(database.Context);
			var classrooms = await classroomService.GetClassroomsWithAccessAsync(userId);
			classrooms = classrooms.OrderBy(c => c.ClassroomId).ToList();

			Assert.Equal(2, classrooms.Count);
			Assert.Equal(userId, classrooms[0].UserId);
			Assert.Equal(expectedClassrooms[0].Id, classrooms[0].ClassroomId);
			Assert.Equal(userId, classrooms[1].UserId);
			Assert.Equal(expectedClassrooms[1].Id, classrooms[1].ClassroomId);
		}