public async void CreateAsync_BlogPost_from_OLW() { // Arrange: // since the final step of CreateAsync is to call repo.GetAsync, // arrange a post to return postRepoMock.Setup(repo => repo.GetAsync(It.IsAny <int>(), EPostType.BlogPost)) .Returns(Task.FromResult(new Post { CreatedOn = DateTimeOffset.Now })); // Act: // user creates a new blog post from OLW, this post omits values that are // typically missed when posting from OLW var blogPostCreated = await blogPostService.CreateAsync(new BlogPost { UserId = Actor.ADMIN_ID, Title = "Hello World!", Slug = null, // user didn't input Body = "This is my first post", Excerpt = null, // user didn't input CategoryTitle = null, // coming from olw CatTitle is used instead of CatId TagTitles = null, // user didn't input CreatedOn = new DateTimeOffset(), // user didn't input, it's MinValue Status = EPostStatus.Published, CommentStatus = ECommentStatus.AllowComments, }); // Assert: // mediatr publishes null cat title mediatorMock.Verify(m => m.Publish( It.Is <BlogPostBeforeCreate>(e => e.CategoryTitle == null && e.TagTitles == null ), cancellationToken), Times.Once); // repo.CreateAsync is called once with the following conditions postRepoMock.Verify(repo => repo.CreateAsync( It.Is <Post>(p => p.Slug == "hello-world" && // Slug is generated p.CreatedOn != new DateTimeOffset() && // CreatedOn is set to now instead of min value p.Excerpt == null // Excerpt is not generated on user's behalf ), null, null), Times.Once); // the date displays human friend string var coreSettings = new CoreSettings(); Assert.Equal("now", blogPostCreated.CreatedOn.ToDisplayString(coreSettings.TimeZoneId)); }