Во время разработки ПО поднимается много интересных вопросов - мелких и не очень. Чтобы самому не забыть, да и другим разработчикам в помощь - буду выкладывать их здесь
Долго не мог понять, почему не подходит стандартная строка форматирования, например "HH:mm:ss". И "hh:mm:ss". И только почти случайно обнаружил, что работает оно так: Value.ToString("hh':'mm':'ss")
Дела делаются быстро, если под руками толковый пример кода. Собственно, лежит этот пример здесь: https://github.com/dotnet/EntityFramework.Docs/blob/live/samples/core/Testing/TestingWithoutTheDatabase/SqliteInMemoryBloggingControllerTest.cs. Статья про тестирование с EF Core (точнее, про одно из направлений тестирования) - здесь: https://learn.microsoft.com/en-us/ef/core/testing/testing-without-the-database. Как мне вообще понадобились такие интеграционные тесты? Ну, есть кой-какие моменты, которые хочется прояснить на уровне тестов. Например, обработка некоторых ошибок взаимодействия с базой. А, кстати...
Неожиданная вещь случилась. Пишу комментарий: /// См. <a href="https://learn.microsoft.com/ru-ru/aspnet/core/test/integration-tests?view=aspnetcore-8.0&pivots=xunit>">Интеграционные тесты на платформе ASP.NET Core</a> Получаю при сборке предупреждение CS1570. Компилятору не нравится, что в URL присутствует символ амперсанда. Потыкал по разному в код, посмотрел доки, попробовал тег "see href". Пока что оставил вот в каком виде: /// См...
Точнее, это должно было быть тестирование профилей для AutoMapper, но тут я как-то задолбался придумывать пути по просовыванию лицензионного ключа непосредственно к тестам, и потому пошел пока что по несколько упрощенному пути. У меня уже есть настроенный на все что нужно проект сервиса. С него стандартным образом используем Program / Main (см. https://dzen.ru/a/aFiU7IOvXDA6zAAQ). И проверяем, получается, конфигурацию AutoMapper целиком, что меня вполне устраивает: public class AutomapperProfileIntegrationTest : IClassFixture<WebApplicationFactory<Program>>
{ private readonly WebApplicationFactory<Program>...
Простая ситуация: в контроллере в конце возвращаем код 201 (Создано), без указания созданного объекта, или его адреса: return Created(); И в тестах с удивлением я обнаруживаю результат с кодом 200 (ОК). После некоторого исследования, я выяснил, что это таки баг: https://github.com/dotnet/aspnetcore/issues/53734. Вроде как этот баг исправлен в рамках ...
Уточняю: тестировать я буду контроллер (см. https://dzen.ru/a/aERZVGOmEkUkVxAm) - с использованием xUnit v3 и пакета Microsoft.AspNetCore.Mvc.Testing. И без Moq. Основная статья, откуда я все это брал - вот: https://learn.microsoft.com/ru-ru/aspnet/core/test/integration-tests?view=aspnetcore-8.0&pivots=xunit. Кстати, для .NET Core 9 там код слегка поменялся, так что при переходе с .NET Core 8 на .NET Core 9 придется менять часть кода в тестовом проекте. Итак. Во-первых, в проекте с сервисами и хостингом сервисов, в точке входа (Program.cs) пришлось немного переделать код: 1. Добавить атрибут: #if DEBUG
[assembly:
InternalsVisibleTo("Foo...
Общая идея такая: если нет каких-то особых условий использования, то лучше использовать EscapeDataString (как минимум, не будет проблем с пробелами). Обсуждение на эту тему можно почитать здесь (https://stackoverflow.com/questions/31156247/httputility-urlencode-vs-uri-escapeuristring-in-net) и здесь (https://stackoverflow...
Иногда бывают такие дни... Фигачишь код, ожидаешь, что будут проблемы на запуске... И проблемы приходят! Практически, до запуска! В общем, такая картина: Тесты найдены. Но их нет. Отличный парадокс, я считаю. Перепробовал я разное. Почитал посты бедолаг, которые переустановили VS, пакеты, Windows - и ничего им не помогло. В конце концов, выход был случайно найден: помогло удаление папки .vs в корне папки решения (оно же solution). К сожалению, не сохранилась ссылка на обсуждение, где был предложен это вариант...
Вот какой код меня только что очень порадовал: public bool IsDatabaseLevelPrimaryKeyViolationError(Exception wrappingException)
{
return wrappingException.GetBaseException() is SqliteException
{
SqliteErrorCode: SqlMainErrorCodes.ConstraintViolation,
SqliteExtendedErrorCode: SqlExtendedErrorCodes...
Для начала о хорошем: если нужно тестировать с использованием Add/Update контекста EF Core, то можно сделать так: mockDbSet.Setup(d => d.Add(It.IsAny<Bar>())).Callback(
delegate(Bar v) { // что-то делаем с Bar v }); mockDbSet.Setup(d => d.Update(It.IsAny<Bar>())).Callback(
delegate(Bar v) { // что-то делаем с Bar v }); И уже для контекста: mockDbContext.Setup(dbContext =>
dbContext.SaveChangesAsync(It.IsAny<CancellationToken>())).ReturnsAsync(() =>
originalData.Count).Callback( delegate { // проверяем сохранение }); Подробнее о настройке mockDbSet и mockDbContext можно посмотреть здесь: https://dzen...
Допустим, есть у меня в тестируемом коде (в контроллере ASP.NET Core) такой вызов: Bar? bar = await _context.FooBars.FindAsync(barName); К сожалению, настройки по умолчанию для заглушки Mock<DbSet<Bar>> тут будет недостаточно (см. https://dzen.ru/a/aERZVGOmEkUkVxAm). Тут потребуется дополнительная настройка, примерно такая: public async Task Test(List<Bar> data)
{
.... Mock<DbSet<Bar>>? mockDbSet = data.AsQueryable().BuildMockDbSet();
mockDbSet.Setup(m => m.FindAsync(It.IsAny<object[]>()))...
Если быть более точным - xUnit 3, Moq 4, MockQueryable.Moq 7, ASP.NET Core 8. В общем, столкнулся я с давно известной сложностью - как тестировать контроллер, если там куча ссылок на контекст EF Core, не используя при этом полноценное соединение с БД. Понятное дело, что вместо контекста EF Core там нужен имитатор, но при этом нормально обрабатывающий все вызовы (на основе тестовых данных). В общем, нашел я пакет MockQueryable.Moq. Это не единственный вариант, но субъективно мне он больше понравился. Этот пакет проделывает значительную часть работы по адаптации использования Moq вместе с EF Core (и не только)...