using System; using System.Threading; using System.Threading.Tasks; using System.Xml; using BirdsiteLive.Common.Settings; using BirdsiteLive.DAL.Contracts; using BirdsiteLive.DAL.Models; using BirdsiteLive.Moderation.Actions; using BirdsiteLive.Pipeline.Models; using BirdsiteLive.Pipeline.Processors; using BirdsiteLive.Pipeline.Processors.SubTasks; using BirdsiteLive.Twitter.Models; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; namespace BirdsiteLive.Pipeline.Tests.Processors { [TestClass] public class SendTweetsToFollowersProcessorTests { [TestMethod] public async Task ProcessAsync_SameInstance_SharedInbox_OneTweet_Test() { #region Stubs var tweetId = 1; var host = "domain.ext"; var sharedInbox = "/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new [] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new [] { new Follower { Id = userId1, Host = host, SharedInboxRoute = sharedInbox }, new Follower { Id = userId2, Host = host, SharedInboxRoute = sharedInbox }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host), It.Is(y => y.Length == 2))) .Returns(Task.CompletedTask); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_SharedInbox_OneTweet_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var sharedInbox = "/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, SharedInboxRoute = sharedInbox }, new Follower { Id = userId2, Host = host2, SharedInboxRoute = sharedInbox }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); foreach (var host in new [] { host1, host2}) { sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host), It.Is(y => y.Length == 1))) .Returns(Task.CompletedTask); } var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_SharedInbox_OneTweet_Error_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var sharedInbox = "/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, SharedInboxRoute = sharedInbox }, new Follower { Id = userId2, Host = host2, SharedInboxRoute = sharedInbox }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host1), It.Is(y => y.Length == 1))) .Returns(Task.CompletedTask); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host2), It.Is(y => y.Length == 1))) .Throws(new Exception()); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 1))) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_SharedInbox_OneTweet_ErrorReset_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var sharedInbox = "/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, SharedInboxRoute = sharedInbox }, new Follower { Id = userId2, Host = host2, SharedInboxRoute = sharedInbox, PostingErrorCount = 50 }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host1), It.Is(y => y.Length == 1))) .Returns(Task.CompletedTask); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host2), It.Is(y => y.Length == 1))) .Returns(Task.CompletedTask); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 0))) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_SharedInbox_OneTweet_ErrorAndReset_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var sharedInbox = "/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, SharedInboxRoute = sharedInbox, PostingErrorCount = 50 }, new Follower { Id = userId2, Host = host2, SharedInboxRoute = sharedInbox, PostingErrorCount = 50 }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host1), It.Is(y => y.Length == 1))) .Returns(Task.CompletedTask); sendTweetsToSharedInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Acct == userAcct), It.Is(y => y == host2), It.Is(y => y.Length == 1))) .Throws(new Exception()); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId1 && y.PostingErrorCount == 0))) .Returns(Task.CompletedTask); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 51))) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_SameInstance_Inbox_OneTweet_Test() { #region Stubs var tweetId = 1; var host = "domain.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host, InboxRoute = inbox }, new Follower { Id = userId2, Host = host, InboxRoute = inbox }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); foreach (var userId in new[] { userId1, userId2 }) { sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); } var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, InboxRoute = inbox }, new Follower { Id = userId2, Host = host2, InboxRoute = inbox }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); foreach (var userId in new[] { userId1, userId2 }) { sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); } var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_Error_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, InboxRoute = inbox }, new Follower { Id = userId2, Host = host2, InboxRoute = inbox }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId1), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId2), It.Is(y => y.Acct == userAcct))) .Throws(new Exception()); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 1))) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_Error_SettingsThreshold_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, InboxRoute = inbox }, new Follower { Id = userId2, Host = host2, InboxRoute = inbox, PostingErrorCount = 42 }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId1), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId2), It.Is(y => y.Acct == userAcct))) .Throws(new Exception()); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); var settings = new InstanceSettings { FailingFollowerCleanUpThreshold = 10 }; var removeFollowerMock = new Mock(MockBehavior.Strict); removeFollowerMock .Setup(x => x.ProcessAsync(It.Is(y => y.Id == userId2))) .Returns(Task.CompletedTask); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_Error_MaxThreshold_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, InboxRoute = inbox }, new Follower { Id = userId2, Host = host2, InboxRoute = inbox, PostingErrorCount = 2147483600 }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId1), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId2), It.Is(y => y.Acct == userAcct))) .Throws(new Exception()); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); var loggerMock = new Mock>(); var settings = new InstanceSettings { FailingFollowerCleanUpThreshold = 0 }; var removeFollowerMock = new Mock(MockBehavior.Strict); removeFollowerMock .Setup(x => x.ProcessAsync(It.Is(y => y.Id == userId2))) .Returns(Task.CompletedTask); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_ErrorReset_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, InboxRoute = inbox }, new Follower { Id = userId2, Host = host2, InboxRoute = inbox, PostingErrorCount = 50 }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId1), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId2), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 0))) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } [TestMethod] public async Task ProcessAsync_MultiInstances_Inbox_OneTweet_ErrorAndReset_Test() { #region Stubs var tweetId = 1; var host1 = "domain1.ext"; var host2 = "domain2.ext"; var inbox = "/user/inbox"; var userId1 = 2; var userId2 = 3; var userAcct = "user"; var userWithTweets = new UserWithDataToSync() { Tweets = new[] { new ExtractedTweet { Id = tweetId } }, User = new SyncTwitterUser { Acct = userAcct }, Followers = new[] { new Follower { Id = userId1, Host = host1, InboxRoute = inbox, PostingErrorCount = 50 }, new Follower { Id = userId2, Host = host2, InboxRoute = inbox, PostingErrorCount = 50 }, } }; #endregion #region Mocks var sendTweetsToInboxTaskMock = new Mock(MockBehavior.Strict); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId1), It.Is(y => y.Acct == userAcct))) .Returns(Task.CompletedTask); sendTweetsToInboxTaskMock .Setup(x => x.ExecuteAsync( It.Is(y => y.Length == 1), It.Is(y => y.Id == userId2), It.Is(y => y.Acct == userAcct))) .Throws(new Exception()); var sendTweetsToSharedInboxTaskMock = new Mock(MockBehavior.Strict); var followersDalMock = new Mock(MockBehavior.Strict); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId1 && y.PostingErrorCount == 0))) .Returns(Task.CompletedTask); followersDalMock .Setup(x => x.UpdateFollowerAsync(It.Is(y => y.Id == userId2 && y.PostingErrorCount == 51))) .Returns(Task.CompletedTask); var loggerMock = new Mock>(); var settings = new InstanceSettings(); var removeFollowerMock = new Mock(MockBehavior.Strict); #endregion var processor = new SendTweetsToFollowersProcessor(sendTweetsToInboxTaskMock.Object, sendTweetsToSharedInboxTaskMock.Object, followersDalMock.Object, loggerMock.Object, settings, removeFollowerMock.Object); var result = await processor.ProcessAsync(userWithTweets, CancellationToken.None); #region Validations sendTweetsToInboxTaskMock.VerifyAll(); sendTweetsToSharedInboxTaskMock.VerifyAll(); followersDalMock.VerifyAll(); removeFollowerMock.VerifyAll(); #endregion } } }