public void Reply_UserIdIsLessOrEqualToZero_ThrowsArgumentOutOfRangeException()
        {
            // Arrange
            int commentId = 1;
            string commentText = "comment_text";

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

            // Act and Assert
            Assert.Throws<ArgumentOutOfRangeException>(() => target.Reply(commentId, -1, commentText));
            Assert.Throws<ArgumentOutOfRangeException>(() => target.Reply(commentId, 0, commentText));
        }
        public void Reply_NonexistentUserId_ThrowsUserNotFoundException()
        {
            // Arrange
            Comment comment = new Comment { CommentId = 1 };
            int userId = 2;
            string commentText = "comment_text";

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

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

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

            // Arrange - mock userRepository
            Mock<IUserRepository> userRepositoryMock = new Mock<IUserRepository>();

            userRepositoryMock.Setup(r => r.GetById(userId))
            .Returns((User)null);

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

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

            unitOfWorkMock.SetupGet(u => u.UserRepository)
            .Returns(userRepositoryMock.Object);

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

            // Act and Assert
            Assert.Throws<UserNotFoundException>(() => target.Reply(comment.CommentId, userId, commentText));

            commentRepositoryMock.Verify(
            r =>
            r.GetById(comment.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 == comment.CommentId)), Times.Never);

            userRepositoryMock.Verify(r => r.GetById(userId), Times.Once);

            unitOfWorkMock.Verify(r => r.Save(), Times.Never);
        }
        public void Reply_CommentTextIsNull_ThrowsArgumentNullException()
        {
            // Arrange
            int commentId = 1;
            int userId = 2;

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

            // Act and Assert
            Assert.Throws<ArgumentNullException>(() => target.Reply(commentId, userId, null));
        }
        public void Reply_CommentTreeLevelIsEqualToMaxCommentTreeLevel_ThrowsMaxCommentTreeLevelReachedException()
        {
            // Arrange
            int userId = 1;
            string commentText = "comment_text";
            Comment comment = new Comment { CommentId = 2, TreeLevel = (byte)this._serviceSettings.MaxCommentTreeLevel };

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

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

            commentRepositoryMock.Setup(
            r =>
            r.GetById(comment.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 and Assert
            Assert.Throws<MaxCommentTreeLevelReachedException>(() => target.Reply(comment.CommentId, userId, commentText));

            commentRepositoryMock.Verify(
            r =>
            r.GetById(comment.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 == comment.CommentId)), Times.Never);

            unitOfWorkMock.Verify(r => r.Save(), Times.Never);
        }
        public void Reply_AllCredentialsAreValid_CreatesAndReturnsReply()
        {
            // Arrange
            User user = new User { UserId = 1 };
            string commentText = "comment_text";
            string validatedCommentText = "validated_comment_text";
            Comment[] commentReplies = { new Comment { CommentId = 2 }, new Comment { CommentId = 3 } };

            Comment comment = new Comment { CommentId = 4, ArticleId = 5, Comment1 = commentReplies.ToList() };

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

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

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

            IEnumerable<Comment> newCommentReplies = null;

            commentRepositoryMock.Setup(r => r.Update(It.IsAny<Comment>()))
            .Callback((Comment c) => newCommentReplies = c.Comment1);

            // Arrange - mock userRepository
            Mock<IUserRepository> userRepositoryMock = new Mock<IUserRepository>();

            userRepositoryMock.Setup(r => r.GetById(user.UserId))
            .Returns(user);

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

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

            unitOfWorkMock.SetupGet(u => u.UserRepository)
            .Returns(userRepositoryMock.Object);

            // Arrange - mock commentValidation
            this._commentValidationMock.Setup(v => v.ValidateCommentText(commentText))
            .Returns(validatedCommentText);

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

            // Act
            Comment reply = target.Reply(comment.CommentId, user.UserId, commentText);

            // Assert
            Assert.IsNotNull(reply);
            Assert.AreEqual(user.UserId, reply.UserId);
            Assert.AreEqual(comment.ArticleId, reply.ArticleId);
            Assert.AreEqual(validatedCommentText, reply.Text);
            Assert.IsTrue(new DateTime() != reply.Date);

            Assert.IsNotNull(newCommentReplies);
            Assert.AreEqual(commentReplies.Count() + 1, newCommentReplies.Count());
            Assert.IsTrue(newCommentReplies.Contains(reply));

            commentRepositoryMock.Verify(
            r =>
            r.GetById(comment.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 == comment.CommentId)), Times.Once);

            userRepositoryMock.Verify(r => r.GetById(user.UserId), Times.Once);

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

            this._commentValidationMock.Verify(v => v.ValidateCommentText(commentText), Times.Once);
        }