x单元测试 Servicestack AutoQuery



第一次使用自动查询,我在实现自动查询后在单元测试中遇到了这个问题。它通过 Swagger 手动测试工作正常。所以我有一个这样的获取方法:

public class ItemService : Service
{
public IAutoQueryDb AutoQuery { get; set; }
private readonly IRepository<Item> itemRepository;
public ItemService(IRepository<Item> itemRepository)
{
this.itemRepository = itemRepository;
}
public ItemResponse Get(FindItems query)
{
var response = new ItemResponse();
var q = AutoQuery.CreateQuery(query, Request);
q.Where(x => !x.IsDeleted);
response.Offset = q.Offset.GetValueOrDefault(0);
response.Total = (int)itemRepository.CountByCondition(q);
var queryResult = AutoQuery.Execute(query, q).Results;
foreach (var item in queryResult)
{
response.MultipleResult.Add(item.ToDto());
}
return response;
}
}

请求/响应是这样构建的:

[Route("/item/{Id}", "GET")]
public class Items : IReturn<ItemResponse>
{
public Items() : base()
{
}
public int Id { get; set; }
}
[Route("/item", "GET")]
public class FindItems : QueryDb<Item>
{
public int[] Ids { get; set; }
public string NameContains { get; set; }
}
public class ItemResponse : BaseResponse<ItemDto>
{
public ItemResponse()
{
MultipleResult = new List<ItemDto>();
}
}

和测试:

public void GetAllItems()
{
SeedDatabase();
var service = appHost.Container.Resolve<ItemService>();
var request = new rq.FindItems();
var response = service.Get(request);
Assert.NotNull(response);
Assert.Empty(response.MultipleResult);
}

问题是 CreateQuery 方法中的请求保持为空(当我运行应用程序时,它已正确填充(。那么我应该在 xunit 测试中做什么才能让请求成为正确的对象而不是空?Ofc 我在测试执行时收到空异常。是否有任何机制可以预设请求?感谢您的任何帮助。

//////更新: 我尝试了使用内置客户端建议的不同方法:

[Fact]
public void CanGetAll()
{
var client = new JsonHttpClient(BaseUri);
var all = client.Get(new FindItem());
Assert.Empty(all.Results);
}

请求不再为空,但创建查询仍返回空。我觉得我仍然缺少一个或几个参数,但我不知道在哪里。当我通过 IIS 运行应用程序时,我将 Request 对象与为单元测试创建的应用程序进行了比较,它们看起来相似,但并不相同。

//////SOLUTION
JsonServiceClient 终于成功了。我需要将 AQ 插件添加到测试安装程序类中,并将 Results 属性添加到响应类中,以将结果传递给 QueryResponse 实例。完全不需要更改内置的JasonServiceClient,默认参数就可以了。我无法根据BasicRequest使其工作。但我得到了我需要的东西,现在就足够了。

注意:依赖于IRequest上下文的 AutoQuery 等服务最好由集成测试而不是单元测试提供,但您可以使用BasicRequest注入空的 IRequest,例如:

var service = appHost.Container.Resolve<ItemService>();
service.Request = new BasicRequest();

此外,许多 ServiceStack 功能希望运行已配置的 AppHost,请参阅内存中数据库单元测试,了解如何在测试运行时配置BasicAppHost

下面是自动查询单元测试的示例:

您需要创建自定义自动查询实现,因为自动查询仅为实际服务创建自动查询服务:

[Route("/movies")]
public class QueryMovies : QueryDb<Movie>
{
public string[] Ratings { get; set; }
}
public class MyQueryServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
public object Any(QueryMovies query)
{
var q = AutoQuery.CreateQuery(query, base.Request);
return AutoQuery.Execute(query, q);
}
}

然后,您可以使用AutoQueryFeature配置您的BasicAppHost,并使用要查询的表配置内存中SQLite数据库,例如:

public class AutoQueryUnitTests
{
private ServiceStackHost appHost;
public AutoQueryUnitTests()
{
appHost = new BasicAppHost {
ConfigureAppHost = host => {
host.Plugins.Add(new AutoQueryFeature());
},
ConfigureContainer = container => {
var dbFactory = new OrmLiteConnectionFactory(
":memory:", SqliteDialect.Provider);
container.Register<IDbConnectionFactory>(dbFactory);
using (var db = dbFactory.Open()) {
db.DropAndCreateTable<Movie>();
db.InsertAll(new[] {
new Movie { ... },
});
}
container.RegisterAutoWired<MyQueryServices>();
},
}.Init();
}
[OneTimeTearDown] public void OneTimeTearDown() => appHost.Dispose();
[Test]
public void Can_execute_AutoQueryService_in_UnitTest()
{
var service = appHost.Resolve<MyQueryServices>();
service.Request = new BasicRequest();
var response = (QueryResponse<Movie>) service.Any(
new QueryMovies { Ratings = new[] {"G", "PG-13"} });            
Assert.That(response.Results.Count, Is.EqualTo(5));
}
}

最新更新