xUnit тестирование Servicestack AutoQuery
Я впервые использую AutoQuery, и у меня возникла эта проблема с модульным тестированием после реализации AutoQuery. Он хорошо работает через ручное тестирование Swagger. Итак, у меня есть метод get, подобный этому:
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);
}
Запрос больше не является нулевым, но CreateQuery по-прежнему возвращает нулевое значение. Я чувствую, что мне все еще не хватает параметра или нескольких, но я понятия не имею, где. Я сравнил объект Request, когда запускаю приложение через IIS и приложение, созданное для модульных тестов, и они выглядят похоже, но не одинаково.
//////РЕШЕНИЕ
JsonServiceClient наконец-то сработал. Мне нужно было добавить плагин AQ для тестирования класса настройки и добавить свойство Results в класс Response, чтобы передать результаты в экземпляр QueryResponse. Нет необходимости менять встроенный JasonServiceClient, параметры по умолчанию работают просто отлично. Я не смог заставить его работать на основе BasicRequest, хотя. Но я получил то, что мне было нужно, этого пока достаточно.
1 ответ
Примечание. Такие сервисы, как AutoQuery, зависят от IRequest
контекст лучше всего подходит для интеграционного теста, а не для юнит-теста, но вы можете использовать BasicRequest
ввести пустой IRequest, например:
var service = appHost.Container.Resolve<ItemService>();
service.Request = new BasicRequest();
Кроме того, многие функции ServiceStack ожидают запуска настроенного AppHost, см. "Модульный тест базы данных в памяти", чтобы узнать, как настроить BasicAppHost
пока ваши тесты запущены.
Вот пример модульного теста AutoQuery:
Вам необходимо создать пользовательскую реализацию AutoQuery, поскольку AutoQuery создает службы AutoQuery только для реальных служб:
[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);
}
}
Затем вы можете настроить свой BasicAppHost
с AutoQueryFeature
и База данных 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));
}
}