Почему асинхронные задачи ведут себя иначе в модульном тесте c#? - PullRequest
0 голосов
/ 26 марта 2020

Я пытаюсь покрыть метод RequestAsyn c модульными тестами.

private readonly SemaphoreSlim lockRequest = new SemaphoreSlim(1, 1);

        public async Task<object> RequestAsync(string key, CancellationToken cancellationToken)
        {
            Logger.Info("EnterRequestDataAsync for address" + key);
            await this.lockRequest.WaitAsync(cancellationToken).ConfigureAwait(false);
            try
            {
                return GetValueFromDataBaseAsync(key);
            }
            finally
            {
                this.lockRequest.Release();
                if (this.lockRequest.CurrentCount == 1)
                {
                    Logger.Info("Inside if statement after address " + key);
                    await this.memory.StartPollingAsync(this);
                }

                Logger.Info("ExitRequestDataAsync for address: " + key);
            }
        }

Если точнее, я бы проверил это поведение блокировки в блоке finally. Чтобы убедиться, что StartPollingAsyn c начинает выполняться только после завершения всех других запросов.

        [Test]
        public async Task TestRequestAsyncPendingRequests()
        {
            // Arrange
            this.memoryMock = new Mock<IMemory>();
            int someValue1 = 1;
            int someValue2 = 2;
            await this.store.SetAsync(nameof(someValue1), someValue1, CancellationToken.None);
            await this.store.SetAsync(nameof(someValue2), someValue2, CancellationToken.None);

            // Act
            Task.Run(async () => this.store.RequestAsync(nameof(someValue1), CancellationToken.None));
            Task.Run(async () => this.store.RequestAsync(nameof(someValue2), CancellationToken.None));

            // Assert
            this.memoryMock.Verify(memory => memory.StartPollingAsync(this.store, It.IsAny<string>()), Times.Once());
        }

Но когда я запускаю этот код, у меня другое поведение. В случае, когда я запускаю этот тест локально на моей машине, я получаю этот вывод:

2020-03-26 11:21:54.5821|INFO|EnterRequestAsync for address: someValue1
2020-03-26 11:21:54.5821|INFO|EnterRequestAsync for address: someValue2
2020-03-26 11:21:54.5919|INFO|ExitRequestAsync for address: someValue1
2020-03-26 11:21:54.5919|INFO|Inside if statement after address someValue2
2020-03-26 11:21:54.5919|INFO|ExitRequestAsync for address: someValue2

или (редко)

2020-03-26 11:55:52.0509|INFO|EnterRequestAsync for address: someValue2
2020-03-26 11:55:52.1191|INFO|EnterRequestAsync for address: someValue1
2020-03-26 11:55:52.1191|INFO|Inside if statement after address someValue1
2020-03-26 11:55:52.1520|INFO|ExitRequestAsync for address: someValue1
2020-03-26 11:55:52.1191|INFO|Inside if statement after address someValue2
2020-03-26 11:55:52.1520|INFO|ExitRequestAsync for address: someValue2

Но когда я пу sh этот тест в Дженкинс, Я получил другой вывод:

2020-03-25 13:12:43.8707|INFO|EnterRequestAsync for address: someValue1
2020-03-25 13:12:43.8707|INFO|Inside if statement after address someValue1
2020-03-25 13:12:43.8707|INFO|EnterRequestAsync for address: someValue2
2020-03-25 13:12:43.8707|INFO|Inside if statement after address someValue2
2020-03-25 13:12:43.8707|INFO|ExitRequestAsync for address: someValue1
2020-03-25 13:12:43.8707|INFO|ExitRequestAsync for address: someValue2

Кажется, что он работает синхронно.

Почему это происходит? Есть ли случай, чтобы исправить это, чтобы получить такое же поведение в любом месте?

...