microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/oauth-card-null-ref-bug

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/test/Microsoft.Teams.Bot.Core.UnitTests/MiddlewareTests.cs

230lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text;
5using Microsoft.AspNetCore.Http;
6using Microsoft.Extensions.Configuration;
7using Microsoft.Extensions.Logging.Abstractions;
8using Microsoft.Teams.Bot.Core.Schema;
9using Moq;
10
11namespace Microsoft.Teams.Bot.Core.UnitTests;
12
13public class MiddlewareTests
14{
15 [Fact]
16 public async Task BotApplication_Use_AddsMiddlewareToChain()
17 {
18 BotApplication botApp = CreateBotApplication();
19
20 Mock<ITurnMiddleware> mockMiddleware = new();
21
22 ITurnMiddleware result = botApp.UseMiddleware(mockMiddleware.Object);
23
24 Assert.NotNull(result);
25 }
26
27
28 [Fact]
29 public async Task Middleware_ExecutesInOrder()
30 {
31 BotApplication botApp = CreateBotApplication();
32
33 List<int> executionOrder = [];
34
35 Mock<ITurnMiddleware> mockMiddleware1 = new();
36 mockMiddleware1
37 .Setup(m => m.OnTurnAsync(It.IsAny<BotApplication>(), It.IsAny<CoreActivity>(), It.IsAny<NextTurn>(), It.IsAny<CancellationToken>()))
38 .Callback<BotApplication, CoreActivity, NextTurn, CancellationToken>(async (app, act, next, ct) =>
39 {
40 executionOrder.Add(1);
41 await next(ct);
42 })
43 .Returns(Task.CompletedTask);
44
45 Mock<ITurnMiddleware> mockMiddleware2 = new();
46 mockMiddleware2
47 .Setup(m => m.OnTurnAsync(It.IsAny<BotApplication>(), It.IsAny<CoreActivity>(), It.IsAny<NextTurn>(), It.IsAny<CancellationToken>()))
48 .Callback<BotApplication, CoreActivity, NextTurn, CancellationToken>(async (app, act, next, ct) =>
49 {
50 executionOrder.Add(2);
51 await next(ct);
52 })
53 .Returns(Task.CompletedTask);
54
55 botApp.UseMiddleware(mockMiddleware1.Object);
56 botApp.UseMiddleware(mockMiddleware2.Object);
57
58 CoreActivity activity = new()
59 {
60 Type = ActivityType.Message,
61 Id = "act123"
62 };
63 if (activity.Recipient is not null)
64 {
65 activity.Recipient.Properties["appId"] = "test-app-id";
66 }
67
68 DefaultHttpContext httpContext = CreateHttpContextWithActivity(activity);
69
70 botApp.OnActivity = (act, ct) =>
71 {
72 executionOrder.Add(3);
73 return Task.CompletedTask;
74 };
75
76 await botApp.ProcessAsync(httpContext);
77 int[] expected = [1, 2, 3];
78 Assert.Equal(expected, executionOrder);
79 }
80
81 [Fact]
82 public async Task Middleware_CanShortCircuit()
83 {
84 BotApplication botApp = CreateBotApplication();
85
86 bool secondMiddlewareCalled = false;
87 bool onActivityCalled = false;
88
89 Mock<ITurnMiddleware> mockMiddleware1 = new();
90 mockMiddleware1
91 .Setup(m => m.OnTurnAsync(It.IsAny<BotApplication>(), It.IsAny<CoreActivity>(), It.IsAny<NextTurn>(), It.IsAny<CancellationToken>()))
92 .Returns(Task.CompletedTask); // Don't call next
93
94 Mock<ITurnMiddleware> mockMiddleware2 = new();
95 mockMiddleware2
96 .Setup(m => m.OnTurnAsync(It.IsAny<BotApplication>(), It.IsAny<CoreActivity>(), It.IsAny<NextTurn>(), It.IsAny<CancellationToken>()))
97 .Callback(() => secondMiddlewareCalled = true)
98 .Returns(Task.CompletedTask);
99
100 botApp.UseMiddleware(mockMiddleware1.Object);
101 botApp.UseMiddleware(mockMiddleware2.Object);
102
103 CoreActivity activity = new()
104 {
105 Type = ActivityType.Message,
106 Id = "act123"
107 };
108 if (activity.Recipient is not null)
109 {
110 activity.Recipient.Properties["appId"] = "test-app-id";
111 }
112
113 DefaultHttpContext httpContext = CreateHttpContextWithActivity(activity);
114
115 botApp.OnActivity = (act, ct) =>
116 {
117 onActivityCalled = true;
118 return Task.CompletedTask;
119 };
120
121 await botApp.ProcessAsync(httpContext);
122
123 Assert.False(secondMiddlewareCalled);
124 Assert.False(onActivityCalled);
125 }
126
127 [Fact]
128 public async Task Middleware_ReceivesCancellationToken()
129 {
130 BotApplication botApp = CreateBotApplication();
131
132 CancellationToken receivedToken = default;
133
134 Mock<ITurnMiddleware> mockMiddleware = new();
135 mockMiddleware
136 .Setup(m => m.OnTurnAsync(It.IsAny<BotApplication>(), It.IsAny<CoreActivity>(), It.IsAny<NextTurn>(), It.IsAny<CancellationToken>()))
137 .Callback<BotApplication, CoreActivity, NextTurn, CancellationToken>(async (app, act, next, ct) =>
138 {
139 receivedToken = ct;
140 await next(ct);
141 })
142 .Returns(Task.CompletedTask);
143
144 botApp.UseMiddleware(mockMiddleware.Object);
145
146 CoreActivity activity = new()
147 {
148 Type = ActivityType.Message,
149 Id = "act123"
150 };
151
152 if (activity.Recipient is not null)
153 {
154 activity.Recipient.Properties["appId"] = "test-app-id";
155 }
156
157 DefaultHttpContext httpContext = CreateHttpContextWithActivity(activity);
158
159 CancellationTokenSource cts = new();
160
161 await botApp.ProcessAsync(httpContext, cts.Token);
162
163 Assert.Equal(cts.Token, receivedToken);
164 }
165
166 [Fact]
167 public async Task Middleware_ReceivesActivity()
168 {
169 BotApplication botApp = CreateBotApplication();
170
171 CoreActivity? receivedActivity = null;
172
173 Mock<ITurnMiddleware> mockMiddleware = new();
174 mockMiddleware
175 .Setup(m => m.OnTurnAsync(It.IsAny<BotApplication>(), It.IsAny<CoreActivity>(), It.IsAny<NextTurn>(), It.IsAny<CancellationToken>()))
176 .Callback<BotApplication, CoreActivity, NextTurn, CancellationToken>(async (app, act, next, ct) =>
177 {
178 receivedActivity = act;
179 await next(ct);
180 })
181 .Returns(Task.CompletedTask);
182
183 botApp.UseMiddleware(mockMiddleware.Object);
184
185 CoreActivity activity = new()
186 {
187 Type = ActivityType.Message,
188 Id = "act123"
189 };
190
191 if (activity.Recipient is not null)
192 {
193 activity.Recipient.Properties["appId"] = "test-app-id";
194 }
195
196 DefaultHttpContext httpContext = CreateHttpContextWithActivity(activity);
197
198 await botApp.ProcessAsync(httpContext);
199
200 Assert.NotNull(receivedActivity);
201 Assert.Equal(ActivityType.Message, receivedActivity.Type);
202 }
203
204 private static BotApplication CreateBotApplication() =>
205 new(CreateMockConversationClient(), CreateMockUserTokenClient(), NullLogger<BotApplication>.Instance);
206
207 private static ConversationClient CreateMockConversationClient()
208 {
209 Mock<HttpClient> mockHttpClient = new();
210 return new ConversationClient(mockHttpClient.Object);
211 }
212
213 private static UserTokenClient CreateMockUserTokenClient()
214 {
215 Mock<HttpClient> mockHttpClient = new();
216 Mock<IConfiguration> mockConfig = new();
217 NullLogger<UserTokenClient> logger = NullLogger<UserTokenClient>.Instance;
218 return new UserTokenClient(mockHttpClient.Object, mockConfig.Object, logger);
219 }
220
221 private static DefaultHttpContext CreateHttpContextWithActivity(CoreActivity activity)
222 {
223 DefaultHttpContext httpContext = new();
224 string activityJson = activity.ToJson();
225 byte[] bodyBytes = Encoding.UTF8.GetBytes(activityJson);
226 httpContext.Request.Body = new MemoryStream(bodyBytes);
227 httpContext.Request.ContentType = "application/json";
228 return httpContext;
229 }
230}
231