public async Task ShoutOut_will_shout_the_given_username() { // arrange var userName = "******"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatter") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithIsSubscriber(true) .WithMessage($"!so {userName}") .Build(); MockApiWrapper.Setup(x => x.DoesUserExist(userName)).ReturnsAsync(true); MockCollection.Setup(x => x.ExistsAsync(userName.ToLower(), null)) .ReturnsAsync(new FakeExistsResult(true)); MockCollection.Setup(x => x.GetAsync(userName.ToLower(), null)) .ReturnsAsync(new FakeGetResult(new TwitcherProfile())); var shout = new ShoutOut(chatMessage); var expectedMessage = $"Hey everyone, check out @{userName}'s Twitch stream at https://twitch.tv/{userName}"; // act await _handler.Handle(shout, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), expectedMessage, false), Times.Once); }
public async Task No_fanfare_if_there_is_no_user_profile() { // arrange var username = "******"; var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build(); var chatMessage = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build(); var request = new UserHasArrived(chatMessage); // setup: user has NOT arrive recently _mockBucket.Setup(m => m.ExistsAsync($"{username}::arrived_recently")) .ReturnsAsync(false); // setup: don't care about the arrive_recently document being added _mockBucket.Setup(m => m.UpsertAsync(It.IsAny <Document <dynamic> >())); // setup: user does NOT have a profile _mockBucket.Setup(m => m.GetAsync <TwitcherProfile>(username.ToLower())) .ReturnsAsync(new FakeOperationResult <TwitcherProfile> { Value = null }); // act await _handler.Handle(request, CancellationToken.None); // assert _mockTwitchHub.Verify(m => m.ReceiveFanfare(It.IsAny <FanfareInfo>()), Times.Never); }
public async Task Should_insert_message_into_bucket() { // arrange var expectedUsername = "******" + Guid.NewGuid(); var expectedMessage = "some message whatever " + Guid.NewGuid(); var expectedChannel = "mychannel" + Guid.NewGuid(); var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(expectedUsername) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage(expectedMessage) .WithChannel(expectedChannel) .Build(); var request = new StoreMessage(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert _mockBucket.Verify(x => x.InsertAsync(It.Is <Document <ChatMessage> >(d => d.Id != Guid.Empty.ToString())), Times.Once()); _mockBucket.Verify(x => x.InsertAsync(It.Is <Document <ChatMessage> >(d => d.Content.Username == expectedUsername)), Times.Once()); _mockBucket.Verify(x => x.InsertAsync(It.Is <Document <ChatMessage> >(d => d.Content.Message == expectedMessage)), Times.Once()); _mockBucket.Verify(x => x.InsertAsync(It.Is <Document <ChatMessage> >(d => d.Content.Channel == expectedChannel)), Times.Once()); }
public async Task Show_current_project_url() { // arrange var expectedUrl = "http://example.org/foo/bar"; var expectedMessage = $"Current Project is: " + expectedUrl; var projectInfo = new CurrentProjectInfo { Url = new Uri(expectedUrl) }; var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatterusername") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage("!currentproject") .WithChannel("doesntmatterchannel") .Build(); var request = new SayCurrentProject(chatMessage); _mockBucket.Setup(x => x.Get <CurrentProjectInfo>("currentProject")) .Returns(new FakeOperationResult <CurrentProjectInfo> { Success = true, Value = projectInfo }); // act await _handler.Handle(request, CancellationToken.None); // assert _mockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), expectedMessage, false), Times.Once); }
public async Task If_no_current_project_set_show_default_message() { // arrange var expectedDefaultMessage = "I haven't set any current project yet, sorry!"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatterusername") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage("!currentproject") .WithChannel("doesntmatterchannel") .Build(); var request = new SayCurrentProject(chatMessage); _mockBucket.Setup(x => x.Get <CurrentProjectInfo>("currentProject")) .Returns(new FakeOperationResult <CurrentProjectInfo> { Success = false }); // act await _handler.Handle(request, CancellationToken.None); // assert _mockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), expectedDefaultMessage, false), Times.Once); }
[TestCase(true, 0)] // if marker document does exist, don't create/update it public async Task Create_recent_activity_marker_document_if_necessary(bool documentAlreadyExists, int timesCalled) { // arrange var username = "******"; _mockBucket.Setup(x => x.ExistsAsync($"{username}::arrived_recently")) .ReturnsAsync(documentAlreadyExists); var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build(); var chatMessage = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build(); var request = new UserHasArrived(chatMessage); _mockBucket.Setup(x => x.GetAsync <TwitcherProfile>(It.IsAny <string>())) .ReturnsAsync(new FakeOperationResult <TwitcherProfile> { Value = new TwitcherProfile() }); _mockTwitchHub.Setup(x => x.ReceiveFanfare(It.IsAny <FanfareInfo>())); // act await _handler.Handle(request, CancellationToken.None); // assert _mockBucket.Verify(x => x.UpsertAsync( It.Is <Document <dynamic> >(x => x.Id == $"{username}::arrived_recently" && x.Expiry == 12 * 60 * 60 * 1000 // 12 hours ) ), Times.Exactly(timesCalled)); }
public async Task ShoutOut_is_limited_to_mods_and_subs(bool isSub, bool isMod, int numVerified) { // arrange var userToShout = "someusername"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("NonSub") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage($"!so {userToShout}") .WithIsSubscriber(isSub) .WithIsModerator(isMod) .Build(); var request = new ShoutOut(chatMessage); MockApiWrapper.Setup(m => m.DoesUserExist(It.IsAny <string>())).ReturnsAsync(true); MockCollection.Setup(m => m.ExistsAsync(userToShout, null)) .ReturnsAsync(new FakeExistsResult(true)); MockCollection.Setup(m => m.GetAsync(userToShout, null)) .ReturnsAsync(new FakeGetResult(new TwitcherProfile())); // act await _handler.Handle(request, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), It.IsAny <string>(), false), Times.Exactly(numVerified)); }
public void FakeRaiseMessage(string message, string channelName = null, string username = null) { if (channelName == null) { channelName = "fakeChannelName"; } if (username == null) { username = "******"; } var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(username) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithChannel(channelName) .WithMessage(message) .Build(); var handler = OnMessageReceived; if (handler == null) { throw new Exception("In FakeRaiseMessage: No handler has been defined."); } handler.Invoke(this, new OnMessageReceivedArgs { ChatMessage = chatMessage }); }
public async Task Create_recent_activity_marker_document_if_necessary() { // arrange var username = "******"; MockCollection.Setup(x => x.ExistsAsync($"{username}::arrived_recently", null)) .ReturnsAsync(new FakeExistsResult(false)); var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build(); var chatMessage = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build(); var request = new UserHasArrived(chatMessage); MockCollection.Setup(x => x.GetAsync(It.IsAny <string>(), null)) .ReturnsAsync(new FakeGetResult(new TwitcherProfile())); _mockTwitchHub.Setup(x => x.ReceiveFanfare(It.IsAny <FanfareInfo>())); // act await _handler.Handle(request, CancellationToken.None); // assert MockCollection.Verify(x => x.UpsertAsync( It.Is <string>(k => k == $"{username}::arrived_recently"), It.IsAny <UserHasArrivedMarker>(), It.IsAny <UpsertOptions>()), Times.Once); MockCollection.Verify(x => x.UpsertAsync( It.IsAny <string>(), It.IsAny <UserHasArrivedMarker>(), It.Is <UpsertOptions>(u => (u.GetInternalPropertyValue <TimeSpan, UpsertOptions>("ExpiryValue")).Hours == 12)), Times.Once); }
public async Task Send_farfare_notice_when_user_has_fanfare_and_is_arriving(bool hasFanfare, int timesSent) { // arrange var username = "******"; var expectedFanfare = new FanfareInfo { Message = "message " + Guid.NewGuid(), Timeout = 12312, YouTubeCode = "ytcode" + Guid.NewGuid(), YouTubeStartTime = 111, YouTubeEndTime = 222 }; var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build(); var chatMessage = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build(); var request = new UserHasArrived(chatMessage); MockCollection.Setup(x => x.ExistsAsync($"{username}::arrived_recently", null)) .ReturnsAsync(new FakeExistsResult(false)); MockCollection.Setup(x => x.GetAsync(It.IsAny <string>(), null)) .ReturnsAsync(new FakeGetResult(new TwitcherProfile { HasFanfare = hasFanfare, Fanfare = expectedFanfare })); // act await _handler.Handle(request, CancellationToken.None); // assert _mockTwitchHub.Verify(x => x.ReceiveFanfare(expectedFanfare), Times.Exactly(timesSent)); }
public async Task Is_chat_message_stored() { // arrange var expectedUsername = "******" + Guid.NewGuid(); var expectedMessage = "some message whatever " + Guid.NewGuid(); var expectedChannel = "mychannel" + Guid.NewGuid(); var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(expectedUsername) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage(expectedMessage) .WithChannel(expectedChannel) .Build(); var request = new StoreMessage(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert var n1ql = $"SELECT RAW COUNT(*) FROM `{Bucket.Name}` WHERE message = $expectedMessage"; var result = await TestCluster.QueryAsync <int>(n1ql, QueryOptions.Create().Parameter("expectedMessage", expectedMessage).ScanConsistency(QueryScanConsistency.RequestPlus)); var count = await result.Rows.FirstOrDefaultAsync(); Assert.That(count, Is.EqualTo(1)); }
public async Task ShoutOut_will_use_custom_message_if_there_is_one() { // arrange var userProfile = new TwitcherProfile { ShoutMessage = "hey hey look at me" + Guid.NewGuid() }; var userName = "******"; var expectedShoutMessage = userProfile.ShoutMessage + $" https://twitch.tv/{userName}"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatter") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithIsSubscriber(true) .WithMessage($"!so {userName}") .Build(); MockApiWrapper.Setup(x => x.DoesUserExist(userName)).ReturnsAsync(true); MockCollection.Setup(x => x.ExistsAsync(userName.ToLower(), null)) .ReturnsAsync(new FakeExistsResult(true)); MockCollection.Setup(x => x.GetAsync(userName.ToLower(), null)) .ReturnsAsync(new FakeGetResult(userProfile)); var shout = new ShoutOut(chatMessage); // act await _handler.Handle(shout, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), expectedShoutMessage, false), Times.Once); }
public async Task ShoutOut_WILL_shout_if_the_given_username_is_a_real_twitch_user() { // arrange var userLookup = "doesntmattereither"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatter") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithIsSubscriber(true) .WithMessage($"!so {userLookup}") .Build(); MockApiWrapper.Setup(x => x.DoesUserExist(userLookup)).ReturnsAsync(true); MockCollection.Setup(x => x.ExistsAsync(userLookup.ToLower(), null)) .ReturnsAsync(new FakeExistsResult(true)); MockCollection.Setup(x => x.GetAsync(userLookup.ToLower(), null)) .ReturnsAsync(new FakeGetResult(new TwitcherProfile())); var shout = new ShoutOut(chatMessage); // act await _handler.Handle(shout, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), It.IsAny <string>(), false), Times.Once); }
public async Task Should_insert_message_into_bucket() { // arrange var expectedUsername = "******" + Guid.NewGuid(); var expectedMessage = "some message whatever " + Guid.NewGuid(); var expectedChannel = "mychannel" + Guid.NewGuid(); var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(expectedUsername) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage(expectedMessage) .WithChannel(expectedChannel) .Build(); var request = new StoreMessage(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert MockCollection.Verify(x => x.InsertAsync(It.IsAny <string>(), It.IsAny <ChatMessage>(), null), Times.Once()); MockCollection.Verify(x => x.InsertAsync(It.IsAny <string>(), It.Is <ChatMessage>(d => d.Username == expectedUsername), null), Times.Once()); MockCollection.Verify(x => x.InsertAsync(It.IsAny <string>(), It.Is <ChatMessage>(d => d.Message == expectedMessage), null), Times.Once()); MockCollection.Verify(x => x.InsertAsync(It.IsAny <string>(), It.Is <ChatMessage>(d => d.Channel == expectedChannel), null), Times.Once()); }
public void Setup() { _twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatter") .Build(); _mockMediator = new Mock <IMediator>(); _factory = new TwitchCommandRequestFactory(_mockMediator.Object); // setup a soundeffect to be a valid sound effect _mockMediator.Setup(x => x.Send <ValidSoundEffects>(It.IsAny <SoundEffectLookup>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new ValidSoundEffects { SoundEffects = new List <SoundEffectInfo> { new SoundEffectInfo { SoundEffectName = "!soundeffect" } } }); // setup a content command to be a valid content command _mockMediator.Setup(x => x.Send <ValidStaticCommands>(It.IsAny <StaticCommandsLookup>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new ValidStaticCommands { Commands = new List <StaticCommandInfo> { new StaticCommandInfo { Command = "staticcommand", Content = "bar" } } }); }
public WhenOnMessageReceived() { ExpectedMessage = Guid.NewGuid().ToString(); ExpectedDisplayName = Guid.NewGuid().ToString(); ChatMessage = ChatMessageBuilder .Create() .WithTwitchLibMessage(TwitchLibMessageBuilder .Create() .WithDisplayName(ExpectedDisplayName)) .WithMessage(ExpectedMessage) .Build(); }
public void ShouldIgnoreUser(String input) { foreach (String id in TwitchUserIDs.ChannelBots) { Boolean result = Sut.TryValidateCommand( ChatMessageBuilder.Create() .WithTwitchLibMessage(TwitchLibMessageBuilder.Create().WithUserId(id).Build()) .WithMessage(input) .Build(), out var userCommandName, out var args); result.Should().BeFalse(); userCommandName.Should().BeNull(); args.Should().BeNull(); } }
public async Task Valid_url_must_be_passed_in(string message) { // arrange var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(_mockOptions.Object.Value.Username) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage(message) .Build(); var request = new SetCurrentProject(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert _mockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), "Sorry, I couldn't understand that URL!", false), Times.Once); }
public void ShouldSetColorFromColorSelector() { var args = new OnMessageReceivedArgs() { ChatMessage = ChatMessageBuilder .Create() .WithTwitchLibMessage(TwitchLibMessageBuilder .Create() .WithUsername(BotUsername) .WithBotUserName(BotUsername)) .WithMessage(Message) .Build() }; Sut.Client_OnMessageReceived(null, args); MockedTwitchClientManager .Verify(x => x.SpoolMessage(PrimaryChannelName, $".color {Color1}", Priority.Medium), Times.Once()); }
public void ShouldDoNothing() { var chatMessage = ChatMessageBuilder .Create() .WithTwitchLibMessage(TwitchLibMessageBuilder .Create() .WithBotUserName(ExpectedBotUsername) .WithUsername(String.Empty) .Build()) .WithMessage(ExpectedMessage) .Build(); Sut.TwitchClient_OnMessageReceived(null, new OnMessageReceivedArgs { ChatMessage = chatMessage }); MockedWriter.Verify(x => x.WriteLine(It.IsAny <String>()), Times.Never()); Assert.True(Sut.WaitingForRepeatMessage); Assert.Equal(default, Sut.RepeatMessage);
public void ShouldIgnoreNonBotUsername() { var args = new OnMessageReceivedArgs() { ChatMessage = ChatMessageBuilder .Create() .WithTwitchLibMessage(TwitchLibMessageBuilder .Create() .WithUsername(Username) .WithBotUserName(BotUsername)) .WithMessage(Message) .Build() }; Sut.Client_OnMessageReceived(null, args); MockedTwitchClientManager .Verify(x => x.SpoolMessage(PrimaryChannelName, It.IsAny <String>(), It.IsAny <Priority>()), Times.Never()); }
public async Task ShoutOut_will_do_nothing_if_no_name_is_given() { // arrange var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername("doesntmatter") .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithIsSubscriber(true) .WithMessage("!so") .Build(); var request = new ShoutOut(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), It.IsAny <string>(), false), Times.Never); }
public async Task Help_with_invalid_arguments_will_just_say_generic_help() { // arrange var expectedChannel = "whateverchannel"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithChannel(expectedChannel) .WithMessage("!help somethingThatIsntACommand") .Build(); var request = new Help(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(expectedChannel, It.Is <string>(s => s.StartsWith("Try these commands:")), false), Times.Once); }
public async Task Help_will_provide_details_on_specific_commands(string messageText, string startsWith) { // arrange var expectedChannel = "whateverchannel"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithChannel(expectedChannel) .WithMessage(messageText) .Build(); var request = new Help(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(expectedChannel, It.Is <string>(s => s.StartsWith(startsWith)), false), Times.Once); }
public void ShouldSendMessage(String message, String expectedMessage) { ChatMessage chatMessage = ChatMessageBuilder .Create() .WithMessage(message) .WithChannel(ChannelName) .WithTwitchLibMessage(TwitchLibMessageBuilder .Create() .WithDisplayName(Players[0].Name)) .Build(); Sut.GetHelp(chatMessage); MockedClient.Verify( x => x.SpoolMessage( ChannelName, It.Is <String>(x => x.Contains(expectedMessage)), Priority.Low), Times.Once()); }
public async Task A_random_lurk_message_is_sent_with_the_users_name() { // arrange var expectedUsername = "******" + Guid.NewGuid(); var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(expectedUsername) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage("!help") .Build(); var req = new Lurk(chatMessage); // act await _handler.Handle(req, CancellationToken.None); // assert _mockTwitchClient.Verify(m => m.SendMessage(It.IsAny <string>(), It.Is <string>(s => s.Contains(expectedUsername)), false), Times.Once); }
public void ShouldRecordRepeatMessage() { var chatMessage = ChatMessageBuilder .Create() .WithTwitchLibMessage(TwitchLibMessageBuilder .Create() .WithBotUserName(ExpectedBotUsername) .WithUsername(ExpectedBotUsername) .Build()) .WithMessage(ExpectedMessage) .Build(); Sut.TwitchClient_OnMessageReceived(null, new OnMessageReceivedArgs { ChatMessage = chatMessage }); MockedWriter.Verify(x => x.WriteLine($"Received repeat message: \"{ExpectedMessage}\""), Times.Once()); Assert.False(Sut.WaitingForRepeatMessage); Assert.Equal(ExpectedMessage, Sut.RepeatMessage); }
public async Task Help_command_will_say_help_to_the_channel() { // arrange var expectedChannel = "whateverchannel"; var twitchLibMessage = TwitchLibMessageBuilder.Create() .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithChannel(expectedChannel) .WithMessage("!help") .Build(); var request = new Help(chatMessage); // act await _handler.Handle(request, CancellationToken.None); // assert _mockTwitchClient.Verify(x => x.SendMessage(expectedChannel, It.Is <string>(s => s.StartsWith("Try these commands:")), false), Times.Once); }
public async Task Says_okay_if_able_to_store() { // arrange var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(MockTwitchOptions.Object.Value.Username) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage("!setcurrentproject http://validurl.com") .Build(); var request = new SetCurrentProject(chatMessage); MockCollection.Setup(x => x.UpsertAsync(It.IsAny <string>(), It.IsAny <CurrentProjectInfo>(), null)) .ReturnsAsync(new FakeMutationResult()); // act await _handler.Handle(request, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), "Okay, got it!", false), Times.Once); }
public async Task Says_an_error_message_if_unable_to_store() { // arrange var twitchLibMessage = TwitchLibMessageBuilder.Create() .WithUsername(MockTwitchOptions.Object.Value.Username) .Build(); var chatMessage = ChatMessageBuilder.Create() .WithTwitchLibMessage(twitchLibMessage) .WithMessage("!setcurrentproject http://validurl.com") .Build(); var request = new SetCurrentProject(chatMessage); MockCollection.Setup(x => x.UpsertAsync(It.IsAny <string>(), It.IsAny <CurrentProjectInfo>(), null)) .Throws <Exception>(); // act await _handler.Handle(request, CancellationToken.None); // assert MockTwitchClient.Verify(x => x.SendMessage(It.IsAny <string>(), "I was unable to store that, sorry!", false), Times.Once); }