Cara menyatukan bot pengujian
BERLAKU UNTUK: SDK v4
Dalam topik ini kami akan menunjukkan kepada Anda cara:
- Buat pengujian unit untuk bot.
- Gunakan pernyataan untuk memeriksa aktivitas yang dikembalikan oleh dialog berbalik terhadap nilai yang diharapkan.
- Gunakan pernyataan untuk memeriksa hasil yang dikembalikan oleh dialog.
- Buat berbagai jenis pengujian berbasis data.
- Buat objek tiruan untuk berbagai dependensi dialog, seperti pengenal bahasa, dan sebagainya.
Prasyarat
Sampel CoreBot Tests yang digunakan dalam topik ini mereferensikan paket Microsoft.Bot.Builder.Testing , XUnit, dan Moq untuk membuat pengujian unit.
Sampel bot inti menggunakan Pemahaman Bahasa (LUIS) untuk mengidentifikasi niat pengguna; namun, mengidentifikasi niat pengguna bukanlah fokus artikel ini. Untuk informasi tentang mengidentifikasi niat pengguna, lihat Pemahaman bahasa alami dan Menambahkan pemahaman bahasa alami ke bot Anda.
Catatan
Pemahaman Bahasa (LUIS) akan dihentikan pada 1 Oktober 2025. Mulai 1 April 2023, Anda tidak akan dapat membuat sumber daya LUIS baru. Versi pemahaman bahasa yang lebih baru sekarang tersedia sebagai bagian dari Bahasa Azure AI.
Pemahaman bahasa percakapan (CLU), fitur Bahasa Azure AI, adalah versi LUIS yang diperbarui. Untuk informasi selengkapnya tentang dukungan pemahaman bahasa di Bot Framework SDK, lihat Pemahaman bahasa alami.
Dialog Pengujian
Dalam sampel CoreBot, dialog adalah unit yang diuji melalui DialogTestClient
kelas , yang menyediakan mekanisme untuk mengujinya dalam isolasi di luar bot dan tanpa harus menyebarkan kode Anda ke layanan web.
Dengan menggunakan kelas ini, Anda dapat menulis pengujian unit yang memvalidasi respons dialog secara bergiliran. Pengujian unit menggunakan DialogTestClient
kelas harus berfungsi dengan dialog lain yang dibangun menggunakan pustaka dialog botbuilder.
Contoh berikut menunjukkan pengujian yang berasal dari DialogTestClient
:
var sut = new BookingDialog();
var testClient = new DialogTestClient(Channels.Msteams, sut);
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
Assert.Equal("Where would you like to travel to?", reply.Text);
reply = await testClient.SendActivityAsync<IMessageActivity>("Seattle");
Assert.Equal("Where are you traveling from?", reply.Text);
reply = await testClient.SendActivityAsync<IMessageActivity>("New York");
Assert.Equal("When would you like to travel?", reply.Text);
reply = await testClient.SendActivityAsync<IMessageActivity>("tomorrow");
Assert.Equal("OK, I will book a flight from Seattle to New York for tomorrow, Is this Correct?", reply.Text);
reply = await testClient.SendActivityAsync<IMessageActivity>("yes");
Assert.Equal("Sure thing, wait while I finalize your reservation...", reply.Text);
reply = testClient.GetNextReply<IMessageActivity>();
Assert.Equal("All set, I have booked your flight to Seattle for tomorrow", reply.Text);
Kelas DialogTestClient
didefinisikan dalam Microsoft.Bot.Builder.Testing
namespace layanan dan disertakan dalam paket NuGet Microsoft.Bot.Builder.Testing .
DialogTestClient
Parameter DialogTestClient
pertama adalah saluran target. Ini memungkinkan Anda menguji logika penyajian yang berbeda berdasarkan saluran target untuk bot Anda (Teams, Slack, dan sebagainya). Jika Anda tidak yakin tentang saluran target, Anda dapat menggunakan Emulator
ID atau Test
saluran tetapi perlu diingat bahwa beberapa komponen mungkin berprilaku berbeda tergantung pada saluran saat ini, misalnya, ConfirmPrompt
merender opsi Ya/Tidak secara berbeda untuk Test
saluran dan Emulator
. Anda juga dapat menggunakan parameter ini untuk menguji logika penyajian kondisional dalam dialog Anda berdasarkan ID saluran.
Parameter kedua adalah instans dialog yang sedang diuji. Dalam kode sampel dalam artikel ini, sut
mewakili sistem yang sedang diuji.
DialogTestClient
Konstruktor menyediakan parameter tambahan yang memungkinkan Anda menyesuaikan perilaku klien lebih lanjut atau meneruskan parameter ke dialog yang sedang diuji jika diperlukan. Anda dapat meneruskan data inisialisasi untuk dialog, menambahkan middleware kustom, atau menggunakan TestAdapter dan ConversationState
instans Anda sendiri.
Mengirim dan menerima pesan
Metode ini SendActivityAsync<IActivity>
memungkinkan Anda mengirim ucapan teks atau IActivity
ke dialog Anda dan mengembalikan pesan pertama yang diterimanya. Parameter <T>
digunakan untuk mengembalikan instans balasan yang diketik yang kuat sehingga Anda dapat menegaskannya tanpa harus mentransmisikannya.
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
Assert.Equal("Where would you like to travel to?", reply.Text);
Dalam beberapa skenario bot Anda dapat mengirim beberapa pesan sebagai respons terhadap satu aktivitas, dalam kasus DialogTestClient
ini akan mengantre balasan dan Anda dapat menggunakan GetNextReply<IActivity>
metode untuk memunculkan pesan berikutnya dari antrean respons.
reply = testClient.GetNextReply<IMessageActivity>();
Assert.Equal("All set, I have booked your flight to Seattle for tomorrow", reply.Text);
GetNextReply<IActivity>
akan mengembalikan null jika tidak ada pesan lebih lanjut dalam antrean respons.
Menegaskan aktivitas
Kode dalam sampel CoreBot hanya menegaskan Text
properti aktivitas yang dikembalikan. Dalam bot yang lebih kompleks, Anda mungkin ingin menegaskan properti lain seperti Speak
, , InputHint
ChannelData
, dan sebagainya.
Assert.Equal("Sure thing, wait while I finalize your reservation...", reply.Text);
Assert.Equal("One moment please...", reply.Speak);
Assert.Equal(InputHints.IgnoringInput, reply.InputHint);
Anda dapat melakukan ini dengan memeriksa setiap properti satu per satu seperti yang ditunjukkan di atas, Anda dapat menulis utilitas pembantu Anda sendiri untuk menegaskan aktivitas atau Anda dapat menggunakan kerangka kerja lain seperti FluentAssertions untuk menulis pernyataan kustom dan menyederhanakan kode pengujian Anda.
Meneruskan parameter ke dialog Anda
DialogTestClient
Konstruktor memiliki initialDialogOptions
yang dapat digunakan untuk meneruskan parameter ke dialog Anda. Misalnya, MainDialog
dalam sampel ini, menginisialisasi objek dari hasil pengenalan bahasa, dengan entitas yang diselesaikannya dari ucapan pengguna, dan meneruskan BookingDetails
objek ini dalam panggilan untuk memanggil BookingDialog
.
Anda dapat menerapkan ini dalam pengujian sebagai berikut:
var inputDialogParams = new BookingDetails()
{
Destination = "Seattle",
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}"
};
var sut = new BookingDialog();
var testClient = new DialogTestClient(Channels.Msteams, sut, inputDialogParams);
BookingDialog
menerima parameter ini dan mengaksesnya dengan cara yang sama seperti saat dipanggil dari MainDialog
.
private async Task<DialogTurnResult> DestinationStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var bookingDetails = (BookingDetails)stepContext.Options;
...
}
Menegaskan hasil giliran dialog
Beberapa dialog seperti BookingDialog
atau DateResolverDialog
mengembalikan nilai ke dialog panggilan. Objek DialogTestClient
mengekspos DialogTurnResult
properti yang dapat digunakan untuk menganalisis dan menegaskan hasil yang dikembalikan oleh dialog.
Contohnya:
var sut = new BookingDialog();
var testClient = new DialogTestClient(Channels.Msteams, sut);
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
Assert.Equal("Where would you like to travel to?", reply.Text);
...
var bookingResults = (BookingDetails)testClient.DialogTurnResult.Result;
Assert.Equal("New York", bookingResults?.Origin);
Assert.Equal("Seattle", bookingResults?.Destination);
Assert.Equal("2019-06-21", bookingResults?.TravelDate);
Properti DialogTurnResult
juga dapat digunakan untuk memeriksa dan menegaskan hasil menengah yang dikembalikan oleh langkah-langkah di air terjun.
Menganalisis output pengujian
Terkadang perlu membaca transkrip pengujian unit untuk menganalisis eksekusi pengujian tanpa harus men-debug pengujian.
Paket Microsoft.Bot.Builder.Testing menyertakan XUnitDialogTestLogger
yang mencatat pesan yang dikirim dan diterima oleh dialog ke konsol.
Untuk menggunakan middleware ini, pengujian Anda perlu mengekspos konstruktor yang menerima ITestOutputHelper
objek yang disediakan oleh runner pengujian XUnit dan membuat XUnitDialogTestLogger
yang akan diteruskan melalui DialogTestClient
middlewares
parameter .
public class BookingDialogTests
{
private readonly IMiddleware[] _middlewares;
public BookingDialogTests(ITestOutputHelper output)
: base(output)
{
_middlewares = new[] { new XUnitDialogTestLogger(output) };
}
[Fact]
public async Task SomeBookingDialogTest()
{
// Arrange
var sut = new BookingDialog();
var testClient = new DialogTestClient(Channels.Msteams, sut, middlewares: _middlewares);
...
}
}
Berikut adalah contoh log XUnitDialogTestLogger
ke jendela output saat dikonfigurasi:
Untuk informasi tambahan tentang mengirim output pengujian ke konsol saat menggunakan XUnit, lihat Menangkap Output dalam dokumentasi XUnit.
Output ini juga akan dicatat di server build selama build integrasi berkelanjutan dan membantu Anda menganalisis kegagalan build.
Pengujian Berbasis Data
Dalam kebanyakan kasus, logika dialog tidak berubah dan jalur eksekusi yang berbeda dalam percakapan didasarkan pada ucapan pengguna. Daripada menulis satu pengujian unit untuk setiap varian dalam percakapan, lebih mudah untuk menggunakan pengujian berbasis data (juga dikenal sebagai pengujian berparameter).
Misalnya, pengujian sampel di bagian gambaran umum dokumen ini menunjukkan cara menguji satu alur eksekusi, tetapi tidak yang lain, seperti:
- Apa yang terjadi jika pengguna mengatakan tidak ke konfirmasi?
- Bagaimana jika mereka menggunakan tanggal yang berbeda?
Pengujian berbasis data memungkinkan kami menguji semua permutasi ini tanpa harus menulis ulang pengujian.
Dalam sampel CoreBot, kami menggunakan Theory
pengujian dari XUnit untuk membuat parameter pengujian.
Teori pengujian menggunakan InlineData
Pengujian berikut memeriksa bahwa dialog dibatalkan saat pengguna mengatakan "batal".
[Fact]
public async Task ShouldBeAbleToCancel()
{
var sut = new TestCancelAndHelpDialog();
var testClient = new DialogTestClient(Channels.Test, sut);
var reply = await testClient.SendActivityAsync<IMessageActivity>("Hi");
Assert.Equal("Hi there", reply.Text);
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
reply = await testClient.SendActivityAsync<IMessageActivity>("cancel");
Assert.Equal("Cancelling...", reply.Text);
}
Untuk membatalkan dialog, pengguna dapat mengetik "keluar", "tidak keberatan", dan "menghentikannya". Daripada menulis kasus pengujian baru untuk setiap kata yang mungkin, tulis satu Theory
metode pengujian yang menerima parameter melalui daftar InlineData
nilai untuk menentukan parameter untuk setiap kasus pengujian:
[Theory]
[InlineData("cancel")]
[InlineData("quit")]
[InlineData("never mind")]
[InlineData("stop it")]
public async Task ShouldBeAbleToCancel(string cancelUtterance)
{
var sut = new TestCancelAndHelpDialog();
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
var reply = await testClient.SendActivityAsync<IMessageActivity>("Hi");
Assert.Equal("Hi there", reply.Text);
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
Assert.Equal("Cancelling...", reply.Text);
}
Pengujian baru akan dijalankan empat kali dengan parameter yang berbeda dan setiap kasus akan ditampilkan sebagai item turunan ShouldBeAbleToCancel
di bawah pengujian di Visual Studio Test Explorer. Jika salah satu dari mereka gagal seperti yang ditunjukkan di bawah ini, Anda dapat mengklik kanan dan men-debug skenario yang gagal daripada menjalankan ulang seluruh rangkaian pengujian.
Teori pengujian menggunakan MemberData dan jenis kompleks
InlineData
berguna untuk pengujian berbasis data kecil yang menerima parameter jenis nilai sederhana (string, int, dan sebagainya).
BookingDialog
menerima BookingDetails
objek dan mengembalikan objek baruBookingDetails
. Versi pengujian non-parameter untuk dialog ini akan terlihat sebagai berikut:
[Fact]
public async Task DialogFlow()
{
// Initial parameters
var initialBookingDetails = new BookingDetails
{
Origin = "Seattle",
Destination = null,
TravelDate = null,
};
// Expected booking details
var expectedBookingDetails = new BookingDetails
{
Origin = "Seattle",
Destination = "New York",
TravelDate = "2019-06-25",
};
var sut = new BookingDialog();
var testClient = new DialogTestClient(Channels.Test, sut, initialBookingDetails);
// Act/Assert
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
...
var bookingResults = (BookingDetails)testClient.DialogTurnResult.Result;
Assert.Equal(expectedBookingDetails.Origin, bookingResults?.Origin);
Assert.Equal(expectedBookingDetails.Destination, bookingResults?.Destination);
Assert.Equal(expectedBookingDetails.TravelDate, bookingResults?.TravelDate);
}
Untuk membuat parameter pengujian ini, kami membuat BookingDialogTestCase
kelas yang berisi data kasus pengujian kami. Ini berisi objek awal BookingDetails
, yang diharapkan BookingDetails
dan array string yang berisi ucapan yang dikirim dari pengguna dan balasan yang diharapkan dari dialog untuk setiap giliran.
public class BookingDialogTestCase
{
public BookingDetails InitialBookingDetails { get; set; }
public string[,] UtterancesAndReplies { get; set; }
public BookingDetails ExpectedBookingDetails { get; set; }
}
Kami juga membuat kelas pembantu BookingDialogTestsDataGenerator
yang mengekspos IEnumerable<object[]> BookingFlows()
metode yang mengembalikan koleksi kasus pengujian yang akan digunakan oleh pengujian.
Untuk menampilkan setiap kasus pengujian sebagai item terpisah di Visual Studio Test Explorer, runner uji XUnit mengharuskan jenis kompleks seperti BookingDialogTestCase
mengimplementasikan IXunitSerializable
, untuk menyederhanakan ini, kerangka kerja Bot.Builder.Testing menyediakan TestDataObject
kelas yang Mengimplementasikan antarmuka ini dan dapat digunakan untuk membungkus data kasus pengujian tanpa harus menerapkan IXunitSerializable
.
Berikut adalah fragmen IEnumerable<object[]> BookingFlows()
yang menunjukkan bagaimana kedua kelas digunakan:
public static class BookingDialogTestsDataGenerator
{
public static IEnumerable<object[]> BookingFlows()
{
// Create the first test case object
var testCaseData = new BookingDialogTestCase
{
InitialBookingDetails = new BookingDetails(),
UtterancesAndReplies = new[,]
{
{ "hi", "Where would you like to travel to?" },
{ "Seattle", "Where are you traveling from?" },
{ "New York", "When would you like to travel?" },
{ "tomorrow", $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.Now.AddDays(1):yyyy-MM-dd}. Is this correct? (1) Yes or (2) No" },
{ "yes", null },
},
ExpectedBookingDetails = new BookingDetails
{
Destination = "Seattle",
Origin = "New York",
TravelDate = $"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
},
};
// wrap the test case object into TestDataObject and return it.
yield return new object[] { new TestDataObject(testCaseData) };
// Create the second test case object
testCaseData = new BookingDialogTestCase
{
InitialBookingDetails = new BookingDetails
{
Destination = "Seattle",
Origin = "New York",
TravelDate = null,
},
UtterancesAndReplies = new[,]
{
{ "hi", "When would you like to travel?" },
{ "tomorrow", $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.Now.AddDays(1):yyyy-MM-dd}. Is this correct? (1) Yes or (2) No" },
{ "yes", null },
},
ExpectedBookingDetails = new BookingDetails
{
Destination = "Seattle",
Origin = "New York",
TravelDate = $"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
},
};
// wrap the test case object into TestDataObject and return it.
yield return new object[] { new TestDataObject(testCaseData) };
}
}
Setelah kita membuat objek untuk menyimpan data pengujian dan kelas yang mengekspos kumpulan kasus pengujian, kita menggunakan atribut XUnit MemberData
alih-alih InlineData
untuk memasukkan data ke dalam pengujian, parameter pertama untuk MemberData
adalah nama fungsi statis yang mengembalikan pengumpulan kasus pengujian dan parameter kedua adalah jenis kelas yang mengekspos metode ini.
[Theory]
[MemberData(nameof(BookingDialogTestsDataGenerator.BookingFlows), MemberType = typeof(BookingDialogTestsDataGenerator))]
public async Task DialogFlowUseCases(TestDataObject testData)
{
// Get the test data instance from TestDataObject
var bookingTestData = testData.GetObject<BookingDialogTestCase>();
var sut = new BookingDialog();
var testClient = new DialogTestClient(Channels.Test, sut, bookingTestData.InitialBookingDetails);
// Iterate over the utterances and replies array.
for (var i = 0; i < bookingTestData.UtterancesAndReplies.GetLength(0); i++)
{
var reply = await testClient.SendActivityAsync<IMessageActivity>(bookingTestData.UtterancesAndReplies[i, 0]);
Assert.Equal(bookingTestData.UtterancesAndReplies[i, 1], reply?.Text);
}
// Assert the resulting BookingDetails object
var bookingResults = (BookingDetails)testClient.DialogTurnResult.Result;
Assert.Equal(bookingTestData.ExpectedBookingDetails?.Origin, bookingResults?.Origin);
Assert.Equal(bookingTestData.ExpectedBookingDetails?.Destination, bookingResults?.Destination);
Assert.Equal(bookingTestData.ExpectedBookingDetails?.TravelDate, bookingResults?.TravelDate);
}
Berikut adalah contoh hasil untuk DialogFlowUseCases
pengujian di Visual Studio Test Explorer saat pengujian dijalankan:
Menggunakan Tiruan
Anda dapat menggunakan elemen tiruan untuk hal-hal yang saat ini tidak diuji. Sebagai referensi, tingkat ini umumnya dapat dianggap sebagai pengujian unit dan integrasi.
Meniru elemen sebanyak yang Anda dapat memungkinkan isolasi yang lebih baik dari potongan yang Anda uji. Kandidat untuk elemen tiruan termasuk penyimpanan, adaptor, middleware, alur aktivitas, saluran, dan apa pun yang tidak secara langsung menjadi bagian dari bot Anda. Ini juga dapat melibatkan penghapusan aspek tertentu untuk sementara waktu, seperti middleware yang tidak terlibat di bagian bot yang Anda uji, untuk mengisolasi setiap bagian. Namun, jika Anda menguji middleware, Anda mungkin ingin mengejek bot Anda sebagai gantinya.
Elemen mocking dapat mengambil beberapa bentuk, dari mengganti elemen dengan objek yang diketahui berbeda hingga menerapkan fungsionalitas hello world minimal. Ini juga bisa berupa menghapus elemen, jika tidak perlu, atau memaksanya untuk tidak melakukan apa-apa.
Tiruan memungkinkan kita untuk mengonfigurasi dependensi dialog dan memastikan mereka berada dalam keadaan yang diketahui selama eksekusi pengujian tanpa harus mengandalkan sumber daya eksternal seperti database, model bahasa, atau objek lainnya.
Untuk membuat dialog Anda lebih mudah diuji dan mengurangi dependensinya pada objek eksternal, Anda mungkin perlu menyuntikkan dependensi eksternal dalam konstruktor dialog.
Misalnya, alih-alih membuat BookingDialog
instans di MainDialog
:
public MainDialog()
: base(nameof(MainDialog))
{
...
AddDialog(new BookingDialog());
...
}
Kami meneruskan instans BookingDialog
sebagai parameter konstruktor:
public MainDialog(BookingDialog bookingDialog)
: base(nameof(MainDialog))
{
...
AddDialog(bookingDialog);
...
}
Ini memungkinkan kami mengganti BookingDialog
instans dengan objek tiruan dan menulis pengujian MainDialog
unit tanpa harus memanggil kelas aktual BookingDialog
.
// Create the mock object
var mockDialog = new Mock<BookingDialog>();
// Use the mock object to instantiate MainDialog
var sut = new MainDialog(mockDialog.Object);
var testClient = new DialogTestClient(Channels.Test, sut);
Dialog Tiruan
Seperti yang dijelaskan di atas, MainDialog
memanggil BookingDialog
untuk mendapatkan BookingDetails
objek . Kami menerapkan dan mengonfigurasi instans tiruan BookingDialog
sebagai berikut:
// Create the mock object for BookingDialog.
var mockDialog = new Mock<BookingDialog>();
mockDialog
.Setup(x => x.BeginDialogAsync(It.IsAny<DialogContext>(), It.IsAny<object>(), It.IsAny<CancellationToken>()))
.Returns(async (DialogContext dialogContext, object options, CancellationToken cancellationToken) =>
{
// Send a generic activity so we can assert that the dialog was invoked.
await dialogContext.Context.SendActivityAsync($"{mockDialogNameTypeName} mock invoked", cancellationToken: cancellationToken);
// Create the BookingDetails instance we want the mock object to return.
var expectedBookingDialogResult = new BookingDetails()
{
Destination = "Seattle",
Origin = "New York",
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}"
};
// Return the BookingDetails we need without executing the dialog logic.
return await dialogContext.EndDialogAsync(expectedBookingDialogResult, cancellationToken);
});
// Create the sut (System Under Test) using the mock booking dialog.
var sut = new MainDialog(mockDialog.Object);
Dalam contoh ini, kami menggunakan Moq untuk membuat dialog tiruan dan Setup
metode dan Returns
untuk mengonfigurasi perilakunya.
Mengejek hasil LUIS
Catatan
Pemahaman Bahasa (LUIS) akan dihentikan pada 1 Oktober 2025. Mulai 1 April 2023, Anda tidak akan dapat membuat sumber daya LUIS baru. Versi pemahaman bahasa yang lebih baru sekarang tersedia sebagai bagian dari Bahasa Azure AI.
Pemahaman bahasa percakapan (CLU), fitur Bahasa Azure AI, adalah versi LUIS yang diperbarui. Untuk informasi selengkapnya tentang dukungan pemahaman bahasa di Bot Framework SDK, lihat Pemahaman bahasa alami.
Dalam skenario sederhana, Anda dapat menerapkan hasil LUIS tiruan melalui kode sebagai berikut:
var mockRecognizer = new Mock<IRecognizer>();
mockRecognizer
.Setup(x => x.RecognizeAsync<FlightBooking>(It.IsAny<ITurnContext>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
var luisResult = new FlightBooking
{
Intents = new Dictionary<FlightBooking.Intent, IntentScore>
{
{ FlightBooking.Intent.BookFlight, new IntentScore() { Score = 1 } },
},
Entities = new FlightBooking._Entities(),
};
return Task.FromResult(luisResult);
});
Hasil LUIS bisa menjadi kompleks. Ketika ya, lebih mudah untuk mengambil hasil yang diinginkan dalam file JSON, menambahkannya sebagai sumber daya ke proyek Anda, dan mendeserialisasikannya ke dalam hasil LUIS. Berikut contohnya:
var mockRecognizer = new Mock<IRecognizer>();
mockRecognizer
.Setup(x => x.RecognizeAsync<FlightBooking>(It.IsAny<ITurnContext>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
// Deserialize the LUIS result from embedded json file in the TestData folder.
var bookingResult = GetEmbeddedTestData($"{GetType().Namespace}.TestData.FlightToMadrid.json");
// Return the deserialized LUIS result.
return Task.FromResult(bookingResult);
});