Skip to content

Commit 31048a2

Browse files
committed
make it possible to disable any IPostToBot and IBotToUser, plus tests
1 parent d661eb3 commit 31048a2

File tree

6 files changed

+229
-4
lines changed

6 files changed

+229
-4
lines changed

CSharp/Library/Microsoft.Bot.Builder.Autofac/Dialogs/Conversation.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,40 @@ public static void UpdateContainer(Action<ContainerBuilder> update)
142142
}
143143
}
144144

145+
/// <summary>
146+
/// Disable a specific service type by replacing it with a pass through implementation.
147+
/// </summary>
148+
/// <param name="type">The service type.</param>
149+
/// <param name="builder">The container builder.</param>
150+
public static void Disable(Type type, ContainerBuilder builder)
151+
{
152+
if (typeof(IBotToUser).IsAssignableFrom(type))
153+
{
154+
builder
155+
.RegisterType<PassBotToUser>()
156+
.Keyed<IBotToUser>(type);
157+
}
158+
159+
if (typeof(IPostToBot).IsAssignableFrom(type))
160+
{
161+
builder
162+
.RegisterType<PassPostToBot>()
163+
.Keyed<IPostToBot>(type);
164+
}
165+
}
166+
167+
/// <summary>
168+
/// Disable a specific service type by replacing it with a pass through implementation.
169+
/// </summary>
170+
/// <param name="type">The service type.</param>
171+
public static void Disable(Type type)
172+
{
173+
UpdateContainer(builder =>
174+
{
175+
Disable(type, builder);
176+
});
177+
}
178+
145179
internal static async Task SendAsync(ILifetimeScope scope, IActivity toBot, CancellationToken token = default(CancellationToken))
146180
{
147181
var task = scope.Resolve<IPostToBot>();

CSharp/Library/Microsoft.Bot.Builder.Autofac/Dialogs/DialogModule.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
using System;
3535
using System.IO;
36-
using System.Linq;
3736
using System.Resources;
3837
using System.Text.RegularExpressions;
3938
using System.Threading;
@@ -316,7 +315,11 @@ protected override void Load(ContainerBuilder builder)
316315

317316
builder
318317
.RegisterKeyedType<NullPostToBot, IPostToBot>()
319-
.InstancePerLifetimeScope();
318+
.SingleInstance();
319+
320+
builder
321+
.RegisterKeyedType<PassPostToBot, IPostToBot>()
322+
.InstancePerDependency();
320323

321324
builder
322325
.RegisterKeyedType<EventLoopDialogTask, IPostToBot>()
@@ -389,7 +392,11 @@ protected override void Load(ContainerBuilder builder)
389392

390393
builder
391394
.RegisterKeyedType<NullBotToUser, IBotToUser>()
392-
.InstancePerLifetimeScope();
395+
.SingleInstance();
396+
397+
builder
398+
.RegisterKeyedType<PassBotToUser, IBotToUser>()
399+
.InstancePerDependency();
393400

394401
builder
395402
.RegisterKeyedType<AlwaysSendDirect_BotToUser, IBotToUser>()

CSharp/Library/Microsoft.Bot.Builder/ConnectorEx/BotToUser.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,25 @@ Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellati
8484
}
8585
}
8686

87+
public sealed class PassBotToUser : IBotToUser
88+
{
89+
private readonly IBotToUser inner;
90+
public PassBotToUser(IBotToUser inner)
91+
{
92+
SetField.NotNull(out this.inner, nameof(inner), inner);
93+
}
94+
95+
IMessageActivity IBotToUser.MakeMessage()
96+
{
97+
return this.inner.MakeMessage();
98+
}
99+
100+
async Task IBotToUser.PostAsync(IMessageActivity message, CancellationToken cancellationToken)
101+
{
102+
await this.inner.PostAsync(message, cancellationToken);
103+
}
104+
}
105+
87106
public sealed class AlwaysSendDirect_BotToUser : IBotToUser
88107
{
89108
private readonly IMessageActivity toBot;

CSharp/Library/Microsoft.Bot.Builder/ConnectorEx/PostToBot.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,18 @@ public interface IPostToBot
5959
}
6060

6161
public sealed class NullPostToBot : IPostToBot
62+
{
63+
Task IPostToBot.PostAsync(IActivity activity, CancellationToken token)
64+
{
65+
return Task.CompletedTask;
66+
}
67+
}
68+
69+
public sealed class PassPostToBot : IPostToBot
6270
{
6371
private readonly IPostToBot inner;
6472

65-
public NullPostToBot(IPostToBot inner)
73+
public PassPostToBot(IPostToBot inner)
6674
{
6775
SetField.NotNull(out this.inner, nameof(inner), inner);
6876
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license.
4+
//
5+
// Microsoft Bot Framework: http://botframework.com
6+
//
7+
// Bot Builder SDK GitHub:
8+
// https://github.com/Microsoft/BotBuilder
9+
//
10+
// Copyright (c) Microsoft Corporation
11+
// All rights reserved.
12+
//
13+
// MIT License:
14+
// Permission is hereby granted, free of charge, to any person obtaining
15+
// a copy of this software and associated documentation files (the
16+
// "Software"), to deal in the Software without restriction, including
17+
// without limitation the rights to use, copy, modify, merge, publish,
18+
// distribute, sublicense, and/or sell copies of the Software, and to
19+
// permit persons to whom the Software is furnished to do so, subject to
20+
// the following conditions:
21+
//
22+
// The above copyright notice and this permission notice shall be
23+
// included in all copies or substantial portions of the Software.
24+
//
25+
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
26+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32+
//
33+
34+
using System;
35+
using System.Collections.Generic;
36+
using System.Diagnostics;
37+
using System.Threading;
38+
using System.Threading.Tasks;
39+
using Autofac;
40+
using Microsoft.Bot.Builder.Dialogs;
41+
using Microsoft.Bot.Builder.Dialogs.Internals;
42+
using Microsoft.Bot.Builder.History;
43+
using Microsoft.Bot.Connector;
44+
using Microsoft.VisualStudio.TestTools.UnitTesting;
45+
using Moq;
46+
47+
namespace Microsoft.Bot.Builder.Tests
48+
{
49+
[TestClass]
50+
public sealed class DisableTests : DialogTestBase
51+
{
52+
[TestMethod]
53+
public async Task Disable_PostUnhandledExceptionToUser()
54+
{
55+
var dialog = Chain.PostToChain().Do((c, a) =>
56+
{
57+
throw new Exception("hello");
58+
});
59+
60+
using (var container = Build(Options.ResolveDialogFromContainer))
61+
{
62+
{
63+
var builder = new ContainerBuilder();
64+
builder
65+
.RegisterInstance(dialog)
66+
.As<IDialog<object>>();
67+
builder.Update(container);
68+
}
69+
70+
var toBotText = "hello";
71+
var toUsertText = Debugger.IsAttached ? $"Exception: {toBotText}" : "Sorry, my bot code is having an issue.";
72+
73+
var toBot = MakeTestMessage();
74+
toBot.Text = toBotText;
75+
76+
try
77+
{
78+
await PostActivityAsync(container, toBot, CancellationToken.None);
79+
}
80+
catch
81+
{
82+
}
83+
84+
var queue = container.Resolve<Queue<IMessageActivity>>();
85+
Assert.AreEqual(1, queue.Count);
86+
Assert.AreEqual(toUsertText, queue.Dequeue().Text);
87+
88+
{
89+
var builder = new ContainerBuilder();
90+
Conversation.Disable(typeof(PostUnhandledExceptionToUser), builder);
91+
builder.Update(container);
92+
}
93+
94+
try
95+
{
96+
await PostActivityAsync(container, toBot, CancellationToken.None);
97+
}
98+
catch
99+
{
100+
}
101+
102+
Assert.AreEqual(0, queue.Count);
103+
}
104+
}
105+
106+
[TestMethod]
107+
public async Task Disable_LogBotToUser()
108+
{
109+
var dialog = Chain.PostToChain().Select(m => m.Text).PostToUser().Loop();
110+
111+
var mock = new Mock<IActivityLogger>(MockBehavior.Strict);
112+
mock
113+
.Setup(l => l.LogAsync(It.IsAny<IActivity>()))
114+
.Returns(Task.CompletedTask);
115+
116+
using (var container = Build(Options.ResolveDialogFromContainer))
117+
{
118+
{
119+
var builder = new ContainerBuilder();
120+
builder
121+
.RegisterInstance(dialog)
122+
.As<IDialog<object>>();
123+
builder
124+
.RegisterInstance(mock.Object)
125+
.As<IActivityLogger>();
126+
builder.Update(container);
127+
}
128+
129+
var text = "hello";
130+
131+
await AssertScriptAsync(
132+
container,
133+
text,
134+
text);
135+
136+
mock.VerifyAll();
137+
138+
{
139+
var builder = new ContainerBuilder();
140+
Conversation.Disable(typeof(LogBotToUser), builder);
141+
Conversation.Disable(typeof(LogPostToBot), builder);
142+
builder.Update(container);
143+
}
144+
145+
mock.Reset();
146+
147+
await AssertScriptAsync(
148+
container,
149+
text,
150+
text);
151+
152+
mock.VerifyAll();
153+
}
154+
}
155+
}
156+
}

CSharp/Tests/Microsoft.Bot.Builder.Tests/Microsoft.Bot.Builder.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
<ItemGroup>
9595
<Compile Include="ActivityExTests.cs" />
9696
<Compile Include="BotDataTests.cs" />
97+
<Compile Include="DisableTests.cs" />
9798
<Compile Include="EndConversationTests.cs" />
9899
<Compile Include="BotTests.cs" />
99100
<Compile Include="ChainTests.cs" />

0 commit comments

Comments
 (0)