路桥网站建设,做网站分成,北京asp网站设计制作,信息网站建设预算每一个Teams bot实际上就是一个web api服务#xff0c;这个服务通过Bot Framework和Teams进行通讯#xff0c;所以对于Teams app的测试就是对于一个api service的测试。
软件行业发展到如今#xff0c;测试技术已经趋于成熟。单元测试#xff0c;冒烟测试#xff0c;整合…每一个Teams bot实际上就是一个web api服务这个服务通过Bot Framework和Teams进行通讯所以对于Teams app的测试就是对于一个api service的测试。
软件行业发展到如今测试技术已经趋于成熟。单元测试冒烟测试整合测试。。。等等。那什么是Service level的测试。这里所谓的服务级的测试类似于Integration Test就是指把整个api服务看成是一个黑盒对这个服务的各个api接口作为最小单位进行测试。与Integration Test不同之处在于Service level测试更加侧重于服务本身可以尽量mock掉服务的外部依赖项。
Service Level的测试在如今微服务的时代特别实用如果使用大量的单元测试把每个class的每个方法都层层保护一旦将来改动了代码对测试代码的更新也是一个较大的工作量也就是说代码被测试限制的特别死。相反微服务的时代因为每个服务都不会非常大我们需要给代码一些改动的空间我们关心的是每个api接口对于传入的输入是否可以产生正确的输出。
而且我在使用ServiceLevel测试对我的抽奖机器人进行测试的时候能够很好的发现很多dead code就是一些永远也不会被执行到的死代码。这些代码应该会删掉保持代码的简洁。
那如何做呢ASP.NET Core早就为我们准备好了ServiceLevel测试的利器TestServer。微软官方文档里也有很多介绍如何使用TestServer来做整合测试我们来看一个最简单的例子
public class TestServerFixture : IDisposable
{private readonly TestServer _testServer;public HttpClient Client { get; }public TestServerFixture(){var builder new WebHostBuilder().UseEnvironment(Development).UseStartupStartup();_testServer new TestServer(builder);Client _testServer.CreateClient();}public void Dispose(){Client.Dispose();_testServer.Dispose();}
}[Fact]
public async Task WhenGetMethodIsInvokedWithoutAValidToken_GetShouldAnswerUnAuthorized()
{using (TestServerFixture fixture new TestServerFixture()){// Actvar response await fixture.Client.GetAsync(/api/values/5);// Assertresponse.StatusCode.Should().Be(HttpStatusCode.Unauthorized);}
}当然由于LuckyDraw bot里使用到了很多Azure table storage服务我们在测试中不应该使用真实的azure storage不然多个测试用例并发执行的时候数据肯定就乱掉了而且会相互冲突导致测试结果无法预料。所以在测试的时候我们需要把api服务的外部依赖项都mock掉比如我在LuckyDraw bot里就mock了Bot connector因为在测试中我们不能也不应该真实的往teams里发送东西。
说了这么多还是上代码让大家对这个有一个更加直观的认识
[Fact]
public async Task WhenEverythingIsGood_SendTextHelp_ReplyHelpMessage()
{using (var server CreateServerFixture(ServerFixtureConfigurations.Default))using (var client server.CreateClient()){var response await client.SendTeamsText(atbot name/athelp);response.StatusCode.Should().Be(HttpStatusCode.OK);var createdMessages server.Assert().GetCreatedMessages();createdMessages.Should().HaveCount(1);createdMessages[0].Activity.Text.Should().StartWith(Hi there, To start a lucky draw);}
}public static async TaskHttpResponseMessage SendTeamsText(this HttpClient httpClient,string text,string locale null,double? offsetHours null)
{var activity new Activity{ServiceUrl https://service-url.com,ChannelId msteams,Type ActivityTypes.Message,Text text,Locale locale ?? en-us,LocalTimestamp offsetHours.HasValue ? new DateTimeOffset(2018, 1, 1, 1, 1, 1, 1, TimeSpan.FromHours(offsetHours.Value)) : (DateTimeOffset?)null,From new ChannelAccount(id, name),Recipient new ChannelAccount(bot id, bot name),Conversation new ConversationAccount(isGroup: true, id: conv id, name: conv name),ChannelData new TeamsChannelData{Tenant new TenantInfo { Id Guid.NewGuid().ToString() },Team new TeamInfo { Id Guid.NewGuid().ToString() },Channel new ChannelInfo { Id Guid.NewGuid().ToString() },}};return await httpClient.SendActivity(activity);
}可以看到我们模拟了Teams的Activity把我们自己生成的一个activity传递给了我们api接口然后check了api发送给Teams的消息是不是我们想要的内容。