Можете ли вы проверить, действительно ли функция работает асинхронно?

Я работаю над проектом ASP.NET Web Api, чтобы изучить структуру и ее тестирование, и мне было интересно, можете ли вы проверить, что асинхронные методы на самом деле работают асинхронно (или работают ли они синхронно, например, из-за каких-либо ошибок).

    public class RepositoryBase<Tentity, Tcontext> : IRepositoryBase<Tentity> where Tentity : class where Tcontext : DbContext
    {
        protected Tcontext _RepositoryContext;
        protected DbSet<Tentity> dbSet;
        public RepositoryBase(Tcontext context)
        {
            this._RepositoryContext = context;
            dbSet = _RepositoryContext.Set<Tentity>();
        }
        public async Task Create(Tentity entity)
        {
            await dbSet.AddAsync(entity);
        }
    }

Можете ли вы проверить, действительно ли метод Create работает асинхронно? Логично ли проверять, работает ли метод асинхронно? Или это тривиальная проблема, потому что тот факт, что он возвращает Task, является доказательством того, что он работает асинхронно.

Во время модульного тестирования в моей тестовой функции я только попробовал await repository.Create(testUser);, а затем позже подтвердил, что пользователь внутри базы данных и тот, кого я ввел, идентичны во всех аспектах. Но это всего лишь проверка конечной функциональности функции Create, а не того, успешно ли она работает асинхронно или нет.

Моя цель — не протестировать или подвергнуть сомнению саму эту конкретную структуру, а задаться вопросом, можно ли протестировать какую-либо общую асинхронную функцию на предмет ее асинхронной природы. Приведенный выше пример кода — это всего лишь контекст, при котором этот вопрос появился у меня в голове.

Нет, нет и нет, в порядке вопросов.

GSerg 03.07.2024 11:57

Звучит так, как будто вы не доверяете фреймворку, выполняющему асинхронные действия, когда вы сообщаете фреймворку/среде выполнения, написав соответствующий код, что он должен это делать? Вы намерены тестировать фреймворк/среду выполнения?

Ralf 03.07.2024 11:58

Вы бы проверили внутреннюю часть своей функции. С точки зрения клиента совершенно не имеет значения, действительно ли функция вообще выполняет какой-либо асинхронный код. Вас должно волновать только то, что он возвращает, а это задача. API не дает никаких других обещаний, поэтому вам не следует беспокоиться о других.

MakePeaceGreatAgain 03.07.2024 12:00

@Ральф return Task.FromResult(VerySynchronous());

GSerg 03.07.2024 12:00

@GSerg Затем вы сказали среде выполнения через код, что она не должна быть асинхронной. Для этого нужен тест?

Ralf 03.07.2024 12:03

@Ralf Сама предпосылка вопроса заключается в том, что вы являетесь потребителем функции, которая может делать return Task.FromResult(VerySynchronous());, но вы этого не знаете. Откуда бы вы это узнали, и если бы был способ узнать, что бы вы искали? Ничто из этого не имеет ничего общего с тестированием корректности реализации асинхронности в фреймворке.

GSerg 03.07.2024 12:04

если вы не доверяете фреймворку, в случае framework things вам следует подумать о написании своего собственного. Это вопрос навыков программиста, если его «асинхронный код» работает как синхронный, и почти невозможно проверить это на 100%.

Bartosz 03.07.2024 12:07

@GSerg Я думаю, дело в том, что клиент функции, которая возвращает Task, не должен ожидать, что она будет выполняться асинхронно (всегда). И именно поэтому тестирование, если оно есть, не имеет смысла.

Fildor 03.07.2024 12:10

@WhiteH С точки зрения потребителя все, о чем вас должно волновать, это то, чтобы функция возвращала ожидаемое значение (что Task является наиболее распространенным примером). Кроме того, вы быстро обнаружите, что вам действительно нужно сначала определить «асинхронную работу», чтобы иметь возможность ее протестировать. Вы, например, имеете в виду, что вызываемая функция в какой-то момент переходит в фазу без потока? Я понятия не имею, как вы будете это проверять.

GSerg 03.07.2024 12:10

@GSerg. Он говорит о юниттесте. Итак, предположительно, набор баз данных высмеивается и, по-видимому, выполняет Task.FromResult. Таким образом, в его тесте он будет синхронизирован, тогда как в производстве он может быть асинхронным. Я понимаю вашу точку зрения, но ее невозможно проверить в классическом смысле модульного тестирования.

Ralf 03.07.2024 12:15

«Моя цель состоит в том, чтобы [...] задаться вопросом, следует ли/может ли какая-либо общая асинхронная функция быть проверена на ее асинхронную природу». -- Должен или мог бы? Это два совершенно разных вопроса. Первоначальный вопрос (редакция 1) был о возможности. Если вы хотите узнать о необходимости, я бы предложил задать новый вопрос. К вашему сведению, вопросы по StackOverflow, как ожидается, будут одномерными. Вопросы, в которых задается более чем один вопрос, обычно закрываются по причине «слишком обширно, недостаточно сфокусировано». Однако вопрос о необходимости можно закрыть, поскольку он основан на мнении.

Theodor Zoulias 03.07.2024 12:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
11
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Можете ли вы проверить, действительно ли метод Create работает асинхронно?

Да, но не со 100% уверенностью. Вы можете проверить, что метод возвращает Task, который еще не завершен. Вместо:

await repository.Create(testUser);

...сделай это:

Task task = repository.Create(testUser);
Debug.Assert(!task.IsCompleted);
await task;
  • Если task.IsCompleted ложно, это означает, что в будущем задача будет выполнена асинхронно.
  • Если task.IsCompleted истинно, это означает, что либо оно завершилось синхронно, либо оно завершилось асинхронно настолько быстро, что у вас не было возможности наблюдать за этим (крайне маловероятный сценарий).
Ответ принят как подходящий

ИМХО этот вопрос не имеет особого смысла. Представьте себе такую ​​функцию синхронизации:

int DoSomething(int i) { ... }

С точки зрения потребителя все, что вы знаете (и все, что вам следует проверять), — это то, что ожидает функция и что она возвращает в этом случае. Вы никогда не придете к предположению проверить, действительно ли функция что-нибудь делает с параметром. Вместо этого вы просто проверяете возвращаемое значение.

Ваш асинхронный код ничем не отличается: он возвращает Task, который делает вид, что внутри него выполняется какой-то асинхронный код.

Task DoSomething() { ... }

При вызове этой функции мы заботимся только о ее внешнем виде, а не о ее фактической реализации. У нас нет возможности проверить, что он делает внутри. Мы можем просто предположить, что там есть что-то асинхронное. Даже ключевое слово async нам ничего не говорит. Если бы функция была определена в интерфейсе, async вообще не существовало бы, поэтому на это мы тоже не могли бы полагаться.

Так что, в конце концов, нет смысла проверять, действительно ли функция вызывает какой-либо асинхронный код или она просто делает вид, что это делает; то же, что и в первом примере, если он действительно использует параметр.

«который притворяется, что внутри него работает какой-то асинхронный код» - на самом деле только притворяется, что имеет потенциал для запуска асинхронного кода, верно?

Fildor 03.07.2024 12:13

@fildor ээээхм, ну, когда это asnyc функция, я бы сказал, что функция определенно потенциально может делать что-то асинхронно. Нет await без async. Однако в функции без async да, я понимаю вашу точку зрения.

MakePeaceGreatAgain 03.07.2024 12:15

Точно. Если мы подумаем об интерфейсе, async не будет его частью. Просто возвращаемый тип Task. Любая реализация может иметь это или нет. -- Просто мысль, без каких-либо конкретных замечаний...

Fildor 03.07.2024 12:18

Другие вопросы по теме