public void AddVote_CommentIdIsLessOrEqualToZero_ThrowsArgumentOutOfRangeException()
        {
            // Arrange
            int userId = 1;
            bool voteIsPositive = true;

            ICommentService target = new CommentService(new Mock<IUnitOfWork>().Object, this._commentValidationMock.Object,
            this._serviceSettings);

            // Act and Assert
            Assert.Throws<ArgumentOutOfRangeException>(() => target.AddVote(-1, userId, voteIsPositive));
            Assert.Throws<ArgumentOutOfRangeException>(() => target.AddVote(0, userId, voteIsPositive));
        }
        public void AddVote_NonexistentCommentId_ThrowsCommentNotFoundException()
        {
            // Arrange
            int commentId = 1;
            int userId = 1;
            bool voteIsPositive = true;

            Expression<Func<Comment, object>>[] propertiesToInclude = { c => c.CommentVotes };

            // Arrange - mock commentRepository
            Mock<ICommentRepository> commentRepositoryMock = new Mock<ICommentRepository>();

            commentRepositoryMock.Setup(
            r =>
            r.GetById(commentId,
            It.Is<Expression<Func<Comment, object>>[]>(
            selector => ExpressionHelper.AreExpressionArraysEqual(selector, propertiesToInclude))))
            .Returns((Comment)null);

            // Arrange - mock unitOfWork
            Mock<IUnitOfWork> unitOfWorkMock = new Mock<IUnitOfWork>();

            unitOfWorkMock.SetupGet(u => u.CommentRepository)
            .Returns(commentRepositoryMock.Object);

            // Arrange - create target
            ICommentService target = new CommentService(unitOfWorkMock.Object, this._commentValidationMock.Object,
            this._serviceSettings);

            // Act and Assert
            Assert.Throws<CommentNotFoundException>(() => target.AddVote(commentId, userId, voteIsPositive));

            commentRepositoryMock.Verify(
            r =>
            r.GetById(commentId,
            It.Is<Expression<Func<Comment, object>>[]>(
            selector => ExpressionHelper.AreExpressionArraysEqual(selector, propertiesToInclude))), Times.Once);

            commentRepositoryMock.Verify(r => r.Update(It.Is<Comment>(c => c.CommentId == commentId)), Times.Never);

            unitOfWorkMock.Verify(r => r.Save(), Times.Never);
        }
        public void AddVote_UserHasVotedWithTheSameVoteType_DoNotUpdateTheVote()
        {
            // Arrange
            int commentId = 1;
            int userId = 1;
            bool voteIsPositive = true;

            Comment comment = new Comment
            {
                CommentId = commentId,
                CommentVotes = { new CommentVote { CommentId = commentId, UserId = userId, IsPositive = voteIsPositive } }
            };

            Expression<Func<Comment, object>>[] propertiesToInclude = { c => c.CommentVotes };

            // Arrange - mock commentRepository
            Mock<ICommentRepository> commentRepositoryMock = new Mock<ICommentRepository>();

            commentRepositoryMock.Setup(
            r =>
            r.GetById(commentId,
            It.Is<Expression<Func<Comment, object>>[]>(
            selector => ExpressionHelper.AreExpressionArraysEqual(selector, propertiesToInclude))))
            .Returns(comment);

            // Arrange - mock unitOfWork
            Mock<IUnitOfWork> unitOfWorkMock = new Mock<IUnitOfWork>();

            unitOfWorkMock.SetupGet(u => u.CommentRepository)
            .Returns(commentRepositoryMock.Object);

            // Arrange - create target
            ICommentService target = new CommentService(unitOfWorkMock.Object, this._commentValidationMock.Object,
            this._serviceSettings);

            // Act
            target.AddVote(commentId, userId, voteIsPositive);

            // Assert
            commentRepositoryMock.Verify(
            r =>
            r.GetById(commentId,
            It.Is<Expression<Func<Comment, object>>[]>(
            selector => ExpressionHelper.AreExpressionArraysEqual(selector, propertiesToInclude))), Times.Once);

            commentRepositoryMock.Verify(r => r.Update(It.Is<Comment>(c => c.CommentId == commentId)), Times.Never);

            unitOfWorkMock.Verify(r => r.Save(), Times.Never);
        }
        public void AddVote_UserHasVotedWithAnotherVoteType_EditsVote()
        {
            // Arrange
            int commentId = 1;
            int userId = 1;
            bool voteIsPositive = true;
            CommentVote[] commentVotes =
            {
                new CommentVote { CommentId = commentId, UserId = userId, IsPositive = !voteIsPositive },
                new CommentVote { CommentId = commentId, UserId = userId + 1 },
                new CommentVote { CommentId = commentId, UserId = userId + 2 }
            };

            Comment comment = new Comment { CommentId = commentId, CommentVotes = commentVotes.ToList() };

            Expression<Func<Comment, object>>[] propertiesToInclude = { c => c.CommentVotes };

            // Arrange - mock commentRepository
            Mock<ICommentRepository> commentRepositoryMock = new Mock<ICommentRepository>();

            commentRepositoryMock.Setup(
            r =>
            r.GetById(commentId,
            It.Is<Expression<Func<Comment, object>>[]>(
            selector => ExpressionHelper.AreExpressionArraysEqual(selector, propertiesToInclude))))
            .Returns(comment);

            IEnumerable<CommentVote> newCommentVotes = null;

            commentRepositoryMock.Setup(r => r.Update(It.Is<Comment>(c => c.CommentId == commentId)))
            .Callback((Comment c) => newCommentVotes = c.CommentVotes);

            // Arrange - mock unitOfWork
            Mock<IUnitOfWork> unitOfWorkMock = new Mock<IUnitOfWork>();

            unitOfWorkMock.SetupGet(u => u.CommentRepository)
            .Returns(commentRepositoryMock.Object);

            // Arrange - create target
            ICommentService target = new CommentService(unitOfWorkMock.Object, this._commentValidationMock.Object,
            this._serviceSettings);

            // Act
            target.AddVote(commentId, userId, voteIsPositive);

            // Assert
            Assert.IsNotNull(newCommentVotes);
            Assert.AreEqual(commentVotes.Count(), newCommentVotes.Count());

            CommentVote commentVote =
            newCommentVotes.FirstOrDefault(
            v => v.CommentId == commentId && v.UserId == userId && v.IsPositive == voteIsPositive);

            Assert.IsNotNull(commentVote);

            commentRepositoryMock.Verify(
            r =>
            r.GetById(commentId,
            It.Is<Expression<Func<Comment, object>>[]>(
            selector => ExpressionHelper.AreExpressionArraysEqual(selector, propertiesToInclude))), Times.Once);

            commentRepositoryMock.Verify(r => r.Update(It.Is<Comment>(c => c.CommentId == commentId)), Times.Once);

            unitOfWorkMock.Verify(r => r.Save(), Times.Once);
        }