microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
samples/repro-da

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/test/Microsoft.Teams.Core.UnitTests/ConversationClientTests.cs

636lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Net;
5using System.Text.Json;
6using Microsoft.Extensions.Logging;
7using Microsoft.Extensions.Logging.Abstractions;
8using Microsoft.Teams.Core.Schema;
9using Moq;
10using Moq.Protected;
11
12namespace Microsoft.Teams.Core.UnitTests;
13
14public class ConversationClientTests
15{
16 [Fact]
17 public async Task SendActivityAsync_WithValidActivity_SendsSuccessfully()
18 {
19 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
20 mockHttpMessageHandler
21 .Protected()
22 .Setup<Task<HttpResponseMessage>>(
23 "SendAsync",
24 ItExpr.IsAny<HttpRequestMessage>(),
25 ItExpr.IsAny<CancellationToken>())
26 .ReturnsAsync(new HttpResponseMessage
27 {
28 StatusCode = HttpStatusCode.OK,
29 Content = new StringContent("{\"id\":\"activity123\"}")
30 });
31
32 HttpClient httpClient = new(mockHttpMessageHandler.Object);
33 ConversationClient conversationClient = new(httpClient);
34
35 CoreActivity activity = new()
36 {
37 Type = ActivityType.Message,
38 ServiceUrl = new Uri("https://test.service.url/"),
39 Conversation = new("conv123")
40 };
41
42 SendActivityResponse? result = await conversationClient.SendActivityAsync(activity);
43
44 Assert.NotNull(result);
45 Assert.Contains("activity123", result.Id);
46 }
47
48 [Fact]
49 public async Task SendActivityAsync_WithNullActivity_ThrowsArgumentNullException()
50 {
51 HttpClient httpClient = new();
52 ConversationClient conversationClient = new(httpClient);
53
54 await Assert.ThrowsAsync<ArgumentNullException>(() =>
55 conversationClient.SendActivityAsync(null!));
56 }
57
58 [Fact]
59 public async Task SendActivityAsync_WithNullConversation_ThrowsArgumentNullException()
60 {
61 HttpClient httpClient = new();
62 ConversationClient conversationClient = new(httpClient);
63
64 CoreActivity activity = new()
65 {
66 Type = ActivityType.Message,
67 ServiceUrl = new Uri("https://test.service.url/")
68 };
69
70 await Assert.ThrowsAsync<ArgumentNullException>(() =>
71 conversationClient.SendActivityAsync(activity));
72 }
73
74 [Fact]
75 public async Task SendActivityAsync_WithEmptyConversationId_ThrowsArgumentException()
76 {
77 HttpClient httpClient = new();
78 ConversationClient conversationClient = new(httpClient);
79
80 CoreActivity activity = new()
81 {
82 Type = ActivityType.Message,
83 ServiceUrl = new Uri("https://test.service.url/"),
84 Conversation = new("")
85 };
86
87 await Assert.ThrowsAsync<ArgumentException>(() =>
88 conversationClient.SendActivityAsync(activity));
89 }
90
91 [Fact]
92 public async Task SendActivityAsync_WithNullServiceUrl_ThrowsArgumentNullException()
93 {
94 HttpClient httpClient = new();
95 ConversationClient conversationClient = new(httpClient);
96
97 CoreActivity activity = new()
98 {
99 Type = ActivityType.Message,
100 Conversation = new("conv123")
101 };
102
103 await Assert.ThrowsAsync<ArgumentNullException>(() =>
104 conversationClient.SendActivityAsync(activity));
105 }
106
107 [Fact]
108 public async Task SendActivityAsync_WithHttpError_ThrowsHttpRequestException()
109 {
110 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
111 mockHttpMessageHandler
112 .Protected()
113 .Setup<Task<HttpResponseMessage>>(
114 "SendAsync",
115 ItExpr.IsAny<HttpRequestMessage>(),
116 ItExpr.IsAny<CancellationToken>())
117 .ReturnsAsync(new HttpResponseMessage
118 {
119 StatusCode = HttpStatusCode.BadRequest,
120 Content = new StringContent("Bad request error")
121 });
122
123 HttpClient httpClient = new(mockHttpMessageHandler.Object);
124 ConversationClient conversationClient = new(httpClient);
125
126 CoreActivity activity = new()
127 {
128 Type = ActivityType.Message,
129 ServiceUrl = new Uri("https://test.service.url/"),
130 Conversation = new("conv123")
131 };
132
133 HttpRequestException exception = await Assert.ThrowsAsync<HttpRequestException>(() =>
134 conversationClient.SendActivityAsync(activity));
135
136 Assert.Contains("Error sending activity", exception.Message);
137 Assert.Contains("BadRequest", exception.Message);
138 }
139
140 [Fact]
141 public async Task SendActivityAsync_ConstructsCorrectUrl()
142 {
143 HttpRequestMessage? capturedRequest = null;
144 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
145 mockHttpMessageHandler
146 .Protected()
147 .Setup<Task<HttpResponseMessage>>(
148 "SendAsync",
149 ItExpr.IsAny<HttpRequestMessage>(),
150 ItExpr.IsAny<CancellationToken>())
151 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
152 .ReturnsAsync(new HttpResponseMessage
153 {
154 StatusCode = HttpStatusCode.OK,
155 Content = new StringContent("{\"id\":\"activity123\"}")
156 });
157
158 HttpClient httpClient = new(mockHttpMessageHandler.Object);
159 ConversationClient conversationClient = new(httpClient);
160
161 CoreActivity activity = new()
162 {
163 Type = ActivityType.Message,
164 ServiceUrl = new Uri("https://test.service.url/"),
165 Conversation = new("conv123")
166 };
167
168 await conversationClient.SendActivityAsync(activity);
169
170 Assert.NotNull(capturedRequest);
171 Assert.Equal("https://test.service.url/v3/conversations/conv123/activities/", capturedRequest.RequestUri?.ToString());
172 Assert.Equal(HttpMethod.Post, capturedRequest.Method);
173 }
174
175 [Fact]
176 public async Task SendActivityAsync_WithIsTargeted_AppendsQueryString()
177 {
178 HttpRequestMessage? capturedRequest = null;
179 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
180 mockHttpMessageHandler
181 .Protected()
182 .Setup<Task<HttpResponseMessage>>(
183 "SendAsync",
184 ItExpr.IsAny<HttpRequestMessage>(),
185 ItExpr.IsAny<CancellationToken>())
186 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
187 .ReturnsAsync(new HttpResponseMessage
188 {
189 StatusCode = HttpStatusCode.OK,
190 Content = new StringContent("{\"id\":\"activity123\"}")
191 });
192
193 HttpClient httpClient = new(mockHttpMessageHandler.Object);
194 ConversationClient conversationClient = new(httpClient);
195
196 CoreActivity activity = new()
197 {
198 Type = ActivityType.Message,
199 ServiceUrl = new Uri("https://test.service.url/"),
200 Conversation = new("conv123"),
201 Recipient = new ConversationAccount { IsTargeted = true }
202 };
203
204 await conversationClient.SendActivityAsync(activity);
205
206 Assert.NotNull(capturedRequest);
207 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
208 }
209
210 [Fact]
211 public async Task UpdateActivityAsync_WithIsTargeted_AppendsQueryString()
212 {
213 HttpRequestMessage? capturedRequest = null;
214 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
215 mockHttpMessageHandler
216 .Protected()
217 .Setup<Task<HttpResponseMessage>>(
218 "SendAsync",
219 ItExpr.IsAny<HttpRequestMessage>(),
220 ItExpr.IsAny<CancellationToken>())
221 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
222 .ReturnsAsync(new HttpResponseMessage
223 {
224 StatusCode = HttpStatusCode.OK,
225 Content = new StringContent("{\"id\":\"activity123\"}")
226 });
227
228 HttpClient httpClient = new(mockHttpMessageHandler.Object);
229 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
230
231 CoreActivity activity = new()
232 {
233 Type = ActivityType.Message,
234 ServiceUrl = new Uri("https://test.service.url/")
235 };
236
237 await conversationClient.UpdateActivityAsync("conv123", "activity123", activity, isTargeted: true);
238
239 Assert.NotNull(capturedRequest);
240 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
241 Assert.Equal(HttpMethod.Put, capturedRequest.Method);
242 }
243
244 [Fact]
245 public async Task DeleteActivityAsync_WithIsTargeted_AppendsQueryString()
246 {
247 HttpRequestMessage? capturedRequest = null;
248 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
249 mockHttpMessageHandler
250 .Protected()
251 .Setup<Task<HttpResponseMessage>>(
252 "SendAsync",
253 ItExpr.IsAny<HttpRequestMessage>(),
254 ItExpr.IsAny<CancellationToken>())
255 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
256 .ReturnsAsync(new HttpResponseMessage
257 {
258 StatusCode = HttpStatusCode.OK
259 });
260
261 HttpClient httpClient = new(mockHttpMessageHandler.Object);
262 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
263
264 await conversationClient.DeleteActivityAsync(
265 "conv123",
266 "activity123",
267 new Uri("https://test.service.url/"),
268 isTargeted: true);
269
270 Assert.NotNull(capturedRequest);
271 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
272 Assert.Equal(HttpMethod.Delete, capturedRequest.Method);
273 }
274
275 [Fact]
276 public async Task DeleteActivityAsync_WithActivity_UsesIsTargetedProperty()
277 {
278 HttpRequestMessage? capturedRequest = null;
279 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
280 mockHttpMessageHandler
281 .Protected()
282 .Setup<Task<HttpResponseMessage>>(
283 "SendAsync",
284 ItExpr.IsAny<HttpRequestMessage>(),
285 ItExpr.IsAny<CancellationToken>())
286 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
287 .ReturnsAsync(new HttpResponseMessage
288 {
289 StatusCode = HttpStatusCode.OK
290 });
291
292 HttpClient httpClient = new(mockHttpMessageHandler.Object);
293 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
294
295 CoreActivity activity = new()
296 {
297 Id = "activity123",
298 Type = ActivityType.Message,
299 ServiceUrl = new Uri("https://test.service.url/")
300 };
301
302 await conversationClient.DeleteActivityAsync("conv123", activity, isTargeted: true);
303
304 Assert.NotNull(capturedRequest);
305 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
306 Assert.Equal(HttpMethod.Delete, capturedRequest.Method);
307 }
308
309 [Fact]
310 public async Task UpdateTargetedActivityAsync_AppendsQueryStringWithoutRecipient()
311 {
312 HttpRequestMessage? capturedRequest = null;
313 string? capturedBody = null;
314 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
315 mockHttpMessageHandler
316 .Protected()
317 .Setup<Task<HttpResponseMessage>>(
318 "SendAsync",
319 ItExpr.IsAny<HttpRequestMessage>(),
320 ItExpr.IsAny<CancellationToken>())
321 .Callback<HttpRequestMessage, CancellationToken>(async (req, ct) =>
322 {
323 capturedRequest = req;
324 capturedBody = req.Content != null ? await req.Content.ReadAsStringAsync(ct) : null;
325 })
326 .ReturnsAsync(new HttpResponseMessage
327 {
328 StatusCode = HttpStatusCode.OK,
329 Content = new StringContent("{\"id\":\"activity123\"}")
330 });
331
332 HttpClient httpClient = new(mockHttpMessageHandler.Object);
333 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
334
335 CoreActivity activity = new()
336 {
337 Type = ActivityType.Message,
338 ServiceUrl = new Uri("https://test.service.url/"),
339 };
340
341 await conversationClient.UpdateTargetedActivityAsync("conv123", "activity123", activity);
342
343 Assert.NotNull(capturedRequest);
344 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
345 Assert.Equal(HttpMethod.Put, capturedRequest.Method);
346 Assert.NotNull(capturedBody);
347 Assert.DoesNotContain("isTargeted", capturedBody);
348 }
349
350 [Fact]
351 public async Task DeleteTargetedActivityAsync_AppendsQueryString()
352 {
353 HttpRequestMessage? capturedRequest = null;
354 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
355 mockHttpMessageHandler
356 .Protected()
357 .Setup<Task<HttpResponseMessage>>(
358 "SendAsync",
359 ItExpr.IsAny<HttpRequestMessage>(),
360 ItExpr.IsAny<CancellationToken>())
361 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
362 .ReturnsAsync(new HttpResponseMessage
363 {
364 StatusCode = HttpStatusCode.OK
365 });
366
367 HttpClient httpClient = new(mockHttpMessageHandler.Object);
368 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
369
370 await conversationClient.DeleteTargetedActivityAsync(
371 "conv123",
372 "activity123",
373 new Uri("https://test.service.url/"));
374
375 Assert.NotNull(capturedRequest);
376 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
377 Assert.Equal(HttpMethod.Delete, capturedRequest.Method);
378 }
379
380 [Fact]
381 public async Task SendActivityAsync_WithReplyToId_AppendsReplyToIdToUrl()
382 {
383 HttpRequestMessage? capturedRequest = null;
384 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
385 mockHttpMessageHandler
386 .Protected()
387 .Setup<Task<HttpResponseMessage>>(
388 "SendAsync",
389 ItExpr.IsAny<HttpRequestMessage>(),
390 ItExpr.IsAny<CancellationToken>())
391 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
392 .ReturnsAsync(new HttpResponseMessage
393 {
394 StatusCode = HttpStatusCode.OK,
395 Content = new StringContent("{\"id\":\"activity123\"}")
396 });
397
398 HttpClient httpClient = new(mockHttpMessageHandler.Object);
399 ConversationClient conversationClient = new(httpClient);
400
401 CoreActivity activity = new()
402 {
403 Type = ActivityType.Message,
404 ServiceUrl = new Uri("https://test.service.url/"),
405 Conversation = new("conv123"),
406 ReplyToId = "originalActivity456"
407 };
408
409 await conversationClient.SendActivityAsync(activity);
410
411 Assert.NotNull(capturedRequest);
412 Assert.Equal("https://test.service.url/v3/conversations/conv123/activities/originalActivity456", capturedRequest.RequestUri?.ToString());
413 Assert.Equal(HttpMethod.Post, capturedRequest.Method);
414 }
415
416 [Fact]
417 public async Task SendActivityAsync_WithEmptyReplyToId_DoesNotAppendReplyToIdToUrl()
418 {
419 HttpRequestMessage? capturedRequest = null;
420 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
421 mockHttpMessageHandler
422 .Protected()
423 .Setup<Task<HttpResponseMessage>>(
424 "SendAsync",
425 ItExpr.IsAny<HttpRequestMessage>(),
426 ItExpr.IsAny<CancellationToken>())
427 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
428 .ReturnsAsync(new HttpResponseMessage
429 {
430 StatusCode = HttpStatusCode.OK,
431 Content = new StringContent("{\"id\":\"activity123\"}")
432 });
433
434 HttpClient httpClient = new(mockHttpMessageHandler.Object);
435 ConversationClient conversationClient = new(httpClient);
436
437 CoreActivity activity = new()
438 {
439 Type = ActivityType.Message,
440 ServiceUrl = new Uri("https://test.service.url/"),
441 Conversation = new("conv123"),
442 ReplyToId = ""
443 };
444
445 await conversationClient.SendActivityAsync(activity);
446
447 Assert.NotNull(capturedRequest);
448 Assert.Equal("https://test.service.url/v3/conversations/conv123/activities/", capturedRequest.RequestUri?.ToString());
449 }
450
451 [Fact]
452 public async Task SendActivityAsync_WithAgentsChannel_TruncatesConversationId()
453 {
454 HttpRequestMessage? capturedRequest = null;
455 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
456 mockHttpMessageHandler
457 .Protected()
458 .Setup<Task<HttpResponseMessage>>(
459 "SendAsync",
460 ItExpr.IsAny<HttpRequestMessage>(),
461 ItExpr.IsAny<CancellationToken>())
462 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
463 .ReturnsAsync(new HttpResponseMessage
464 {
465 StatusCode = HttpStatusCode.OK,
466 Content = new StringContent("{\"id\":\"activity123\"}")
467 });
468
469 HttpClient httpClient = new(mockHttpMessageHandler.Object);
470 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
471
472 string longConversationId = new('x', 150);
473 CoreActivity activity = new()
474 {
475 Type = ActivityType.Message,
476 ChannelId = "agents",
477 ServiceUrl = new Uri("https://test.service.url/"),
478 Conversation = new(longConversationId)
479 };
480
481 await conversationClient.SendActivityAsync(activity);
482
483 Assert.NotNull(capturedRequest);
484 string expectedTruncatedId = "acf";
485 Assert.Equal($"https://test.service.url/v3/conversations/{expectedTruncatedId}/activities/", capturedRequest.RequestUri?.ToString());
486 }
487
488 [Fact]
489 public async Task SendActivityAsync_WithRecipientIsTargeted_DeserializedFromJson()
490 {
491 HttpRequestMessage? capturedRequest = null;
492 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
493 mockHttpMessageHandler
494 .Protected()
495 .Setup<Task<HttpResponseMessage>>(
496 "SendAsync",
497 ItExpr.IsAny<HttpRequestMessage>(),
498 ItExpr.IsAny<CancellationToken>())
499 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
500 .ReturnsAsync(new HttpResponseMessage
501 {
502 StatusCode = HttpStatusCode.OK,
503 Content = new StringContent("{\"id\":\"activity123\"}")
504 });
505
506 HttpClient httpClient = new(mockHttpMessageHandler.Object);
507 ConversationClient conversationClient = new(httpClient);
508
509 // Simulate a deserialized activity where isTargeted is set on recipient
510 string activityJson = """
511 {
512 "type": "message",
513 "serviceUrl": "https://test.service.url/",
514 "conversation": { "id": "conv123" },
515 "recipient": { "id": "user1", "isTargeted": true }
516 }
517 """;
518 CoreActivity activity = CoreActivity.FromJsonString(activityJson);
519
520 await conversationClient.SendActivityAsync(activity);
521
522 Assert.NotNull(capturedRequest);
523 Assert.Contains("isTargetedActivity=true", capturedRequest.RequestUri?.ToString());
524 }
525
526 [Fact]
527 public async Task SendActivityAsync_WithJsonElementFrom_ExtractsAgenticIdentity()
528 {
529 HttpRequestMessage? capturedRequest = null;
530 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
531 mockHttpMessageHandler
532 .Protected()
533 .Setup<Task<HttpResponseMessage>>(
534 "SendAsync",
535 ItExpr.IsAny<HttpRequestMessage>(),
536 ItExpr.IsAny<CancellationToken>())
537 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
538 .ReturnsAsync(new HttpResponseMessage
539 {
540 StatusCode = HttpStatusCode.OK,
541 Content = new StringContent("{\"id\":\"activity123\"}")
542 });
543
544 HttpClient httpClient = new(mockHttpMessageHandler.Object);
545 ConversationClient conversationClient = new(httpClient);
546
547 // Simulate a deserialized activity with agentic identity properties in "from"
548 string activityJson = """
549 {
550 "type": "message",
551 "serviceUrl": "https://test.service.url/",
552 "conversation": { "id": "conv123" },
553 "from": { "id": "bot1", "agenticAppId": "app-123", "agenticUserId": "user-456" }
554 }
555 """;
556 CoreActivity activity = CoreActivity.FromJsonString(activityJson);
557
558 await conversationClient.SendActivityAsync(activity);
559
560 // Verify the request was made (agenticIdentity is passed to BotHttpClient via request options)
561 Assert.NotNull(capturedRequest);
562 Assert.Equal(HttpMethod.Post, capturedRequest.Method);
563 }
564
565 [Fact]
566 public async Task SendActivityAsync_WithConversationAccountFrom_ExtractsAgenticIdentity()
567 {
568 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
569 mockHttpMessageHandler
570 .Protected()
571 .Setup<Task<HttpResponseMessage>>(
572 "SendAsync",
573 ItExpr.IsAny<HttpRequestMessage>(),
574 ItExpr.IsAny<CancellationToken>())
575 .ReturnsAsync(new HttpResponseMessage
576 {
577 StatusCode = HttpStatusCode.OK,
578 Content = new StringContent("{\"id\":\"activity123\"}")
579 });
580
581 HttpClient httpClient = new(mockHttpMessageHandler.Object);
582 ConversationClient conversationClient = new(httpClient);
583
584 ConversationAccount from = new() { Id = "bot1", AgenticAppId = "app-123", AgenticUserId = "user-456" };
585
586 CoreActivity activity = new()
587 {
588 Type = ActivityType.Message,
589 ServiceUrl = new Uri("https://test.service.url/"),
590 Conversation = new("conv123"),
591 From = from
592 };
593
594 SendActivityResponse? result = await conversationClient.SendActivityAsync(activity);
595
596 Assert.NotNull(result);
597 }
598
599 [Fact]
600 public async Task SendActivityAsync_WithAgentsChannel_TruncatesConversationIdAndAppendsReplyToId()
601 {
602 HttpRequestMessage? capturedRequest = null;
603 Mock<HttpMessageHandler> mockHttpMessageHandler = new();
604 mockHttpMessageHandler
605 .Protected()
606 .Setup<Task<HttpResponseMessage>>(
607 "SendAsync",
608 ItExpr.IsAny<HttpRequestMessage>(),
609 ItExpr.IsAny<CancellationToken>())
610 .Callback<HttpRequestMessage, CancellationToken>((req, ct) => capturedRequest = req)
611 .ReturnsAsync(new HttpResponseMessage
612 {
613 StatusCode = HttpStatusCode.OK,
614 Content = new StringContent("{\"id\":\"activity123\"}")
615 });
616
617 HttpClient httpClient = new(mockHttpMessageHandler.Object);
618 ConversationClient conversationClient = new(httpClient, NullLogger<ConversationClient>.Instance);
619
620 string longConversationId = new('x', 150);
621 CoreActivity activity = new()
622 {
623 Type = ActivityType.Message,
624 ChannelId = "agents",
625 ServiceUrl = new Uri("https://test.service.url/"),
626 Conversation = new(longConversationId),
627 ReplyToId = "replyActivity789"
628 };
629
630 await conversationClient.SendActivityAsync(activity);
631
632 Assert.NotNull(capturedRequest);
633 string expectedTruncatedId = "acf";
634 Assert.Equal($"https://test.service.url/v3/conversations/{expectedTruncatedId}/activities/replyActivity789", capturedRequest.RequestUri?.ToString());
635 }
636}