xUnit тестирование Servicestack AutoQuery - PullRequest
0 голосов
/ 25 сентября 2018

впервые использую 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, чтобы получить Request для правильного объекта вместо null?Ofc я получаю нулевое исключение при выполнении теста.Есть ли механизм для предварительной установки запроса?Спасибо за любую помощь.

////// ОБНОВЛЕНИЕ: Я попробовал другой подход, как предложено, используя встроенный клиент:

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

Запрос больше не является нулевым, но CreateQuery все еще возвращаетноль.Я чувствую, что мне все еще не хватает параметра или нескольких, но я понятия не имею, где.Я сравнил объект Request, когда запускаю приложение через IIS и приложение, созданное для модульных тестов, и они выглядят похожими, но не одинаковыми.

////// SOLUTION
Наконец-то сработал JsonServiceClient.Мне нужно было добавить плагин AQ для тестирования класса настройки и добавить свойство Results в класс Response, чтобы передать результаты в экземпляр QueryResponse.Нет необходимости менять встроенный JasonServiceClient, параметры по умолчанию работают просто отлично.Я не смог заставить его работать на основе BasicRequest, хотя.Но я получил то, что мне было нужно, этого пока достаточно.

1 Ответ

0 голосов
/ 25 сентября 2018

Примечание. Такие сервисы, как 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));
    }
}
...