With Bunit, my test always pass if I run I lonely. In the contrary, if I run all my 284 tests, I get this error like half the time and I do not know why. This is really frustrating because this is unstable tests.
using Bunit;using LesLumieres.Serveur.Components.Pages.Games;using LesLumieres.Serveur.Data.Services.Interfaces;using LesLumieres.Serveur.Exceptions;using LesLumieres.Serveur.Helper.Interfaces;using LesLumieres.Serveur.Models;using LesLumieres.Serveur.Models.Childs;using LesLumieres.Serveur.Models.Criterias;using LesLumieres.Serveur.Models.Lists;using Microsoft.AspNetCore.Components;using Microsoft.AspNetCore.Components.Authorization;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Microsoft.JSInterop;using Moq;using System.ComponentModel.DataAnnotations;using System.Security.Claims;using TestContext = Bunit.TestContext;namespace LesLumieres.Tests.Components.Pages.Games{ public class ManageGameTest { private TestContext _testContext; private Mock<IGameService> _gameService; private Mock<IParcoursService> _parcoursService; private Mock<ILogger<ManageGame>> _logger; private Mock<IJSRuntime> _js; private Mock<INavigationService> _navigationService; private Mock<AuthenticationStateProvider> _authStateProv; private int _gameId = 23; [SetUp] public void SetUp() { _testContext = new TestContext(); _gameService = new Mock<IGameService>(); _parcoursService = new Mock<IParcoursService>(); _logger = new Mock<ILogger<ManageGame>>(); _js = new Mock<IJSRuntime>(); _navigationService = new Mock<INavigationService>(); _authStateProv = new Mock<AuthenticationStateProvider>(); var fakeUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "Test User"), new Claim(ClaimTypes.Email, "testuser@example.com") }, "mock")); var authState = Task.FromResult(new AuthenticationState(fakeUser)); _authStateProv.Setup(a => a.GetAuthenticationStateAsync()).Returns(authState); _testContext.Services.AddSingleton<IGameService>(_gameService.Object); _testContext.Services.AddSingleton<IParcoursService>(_parcoursService.Object); _testContext.Services.AddSingleton<ILogger<ManageGame>>(_logger.Object); _testContext.Services.AddSingleton<IJSRuntime>(_js.Object); _testContext.Services.AddSingleton<INavigationService>(_navigationService.Object); _testContext.Services.AddSingleton<AuthenticationStateProvider>(_authStateProv.Object); _parcoursService .Setup(ps => ps.GetAll(It.IsAny<ParcoursCriterias>())) .ReturnsAsync(new ParcoursDtoList() { ListParcours = new List<ParcoursDto>() { new ParcoursDto() { Id= 23, Name = "NAME_SUGGESTED_1", Questions = new List<QuestionDto>() { new ChoiceOfAnswerDto(), new ChoiceOfAnswerDto() } }, new ParcoursDto() { Id= 99, Name = "NAME_PARCOURS", Questions = new List<QuestionDto>() { new ChoiceOfAnswerDto(), new ChoiceOfAnswerDto() } } } }); _gameService .Setup(gs => gs.GetAsync(23)) .ReturnsAsync( new GameDto() { Id= 23, Name = "GAME_NAME", GameParcours = new List<GameParcoursDto>() { new GameParcoursDto() { Parcours = new ParcoursDto() { Id = 99, Name = "NAME_PARCOURS" } } }, Players = new List<PlayerDto>() { new PlayerDto() { Name = "PLAYER_1_NOT_MODIFIED", EmojiIcon = "💪", NoOrdre = 1 }, new PlayerDto() { Name = "PLAYER_2_NOT_MODIFIED", EmojiIcon = "💪", NoOrdre = 2 } } } ); } [TearDown] public void TearDown() { _testContext.DisposeComponents(); _testContext.Dispose(); } [Test] public void GivenGame_WhenSaveModifedGame_ThenGameIsSaved() { // Arrange var cut = _testContext.RenderComponent<ManageGame>(args => args .Add(arg => arg.Id, _gameId) ); var gameName = "NAME_OF_THE_GAME"; var inputName = cut.Find("#name"); cut.WaitForState(() => cut.Find("#name") != null, TimeSpan.FromSeconds(15)); cut.Find("#name").Change(new ChangeEventArgs { Value = gameName }); // Act cut.WaitForState(() => cut.Find("#save-game") != null, TimeSpan.FromSeconds(15)); var saveGame = cut.Find("#save-game"); saveGame.Click(); cut.WaitForState(() => cut.Instance.Game.Name == gameName, TimeSpan.FromSeconds(15)); cut.WaitForState(() => cut.Markup.Contains("La partie a bien été modifiée."), TimeSpan.FromSeconds(15)); // Assert Assert.That(cut.Markup.Contains("La partie a bien été modifiée."), Is.True); _gameService.Verify(gs => gs.Modify(It.Is<GameDto>(dto => dto.Name == gameName)), Times.Once); }This is my tested page:
@page "/GererPartie/{Id:int}"@attribute [Authorize()]@inject IGameService GameService@inject ILogger<ManageGame> Logger@inject IJSRuntime JS@inject INavigationService NavigationService@attribute [Authorize()]<Notification Message="@Message" Success="@Success" OnClear="HandleClearNotification" /><ParcoursModal Game="@Game" Save="AddParcours" GameParcours="@GameParcours" /><PlayerModal Game="@Game" Player="@PlayerSelected" Save="AddPlayer" /><div class="container"><h3>@Action une partie</h3><EditForm Model="@Game" OnValidSubmit="OnValidSubmit"><DataAnnotationsValidator /><div class="card"><div class="card-body"><div class="mb-3"><label for="name" class="form-label">Nom</label><InputText id="name" class="form-control" @bind-Value="Game.Name" /><ValidationMessage For="@(() => Game.Name)" /></div><div class="mb-3"><div class="d-flex flex-row"><label for="name" class="form-label">Joueurs</label><button id="add-player" type="button" class="btn btn-primary ms-3" @onclick="() => OpenModalPlayers(null)">Ajouter</button></div><table class="table table-striped"><thead><tr><th>Ajouté</th><th>Ordre de jeu</th><th>Icône</th><th>Nom</th><th>Action</th></tr></thead><tbody> @foreach (var player in Game.Players.OrderBy(p => p.NoOrdre)) {<tr><th> @if (PlayersLoading.Any(pId => pId == player.Name)) {<div class="spinner-grow text-primary" role="status"><span class="visually-hidden">Loading...</span></div> } else {<i class="bi bi-check-circle-fill" style="color:green;font-size:2rem;"></i> }</th><th><b>#@player.NoOrdre</b> @if (player.NoOrdre != 1) {<button id="up-player" type="button" class="btn btn-secondary mx-1" @onclick="() => UpPlayer(player)"><i class="bi bi-arrow-up"></i></button> } @if (player.NoOrdre != Game.Players.Count) {<button id="down-player" type="button" class="btn btn-secondary mx-1" @onclick="() => DownPlayer(player)"><i class="bi bi-arrow-down"></i></button> }</th><th><div class="mx-1 align-self-center">@player.EmojiIcon</div></th><th><div class="mx-1 align-self-center"><b>@player.Name</b></div></th><th><button type="button" class="btn btn-secondary" @onclick="() => OpenModalPlayers(player)">Modifier</button><button id="remove-player" type="button" class="btn btn-secondary" @onclick="() => RemovePlayer(player)">Supprimer</button></th></tr> }</tbody></table></div><div class="mb-3"><div class="d-flex flex-row"><label for="name" class="form-label">Parcours</label><button id="add-parcours" type="button" class="btn btn-primary ms-3" @onclick="() => OpenModalParcours()">Ajouter</button></div><table class="table table-striped"><thead><tr><th>Ajouté</th><th>Nom</th><th>Action</th></tr></thead><tbody> @foreach (var gameParcours in Game.GameParcours) {<tr><th> @if (ParcoursLoading.Any(pId => pId == gameParcours.ParcoursId)) {<div class="spinner-grow text-primary" role="status"><span class="visually-hidden">Loading...</span></div> } else {<i class="bi bi-check-circle-fill" style="color:green;font-size:2rem;"></i> }</th><th><div class="mx-1 align-self-center">@gameParcours.Parcours.Name</div></th><th><button id="remove-parcours" type="button" class="btn btn-secondary" @onclick="() => DeleteParcoursFromGame(gameParcours.ParcoursId)">Supprimer</button></th></tr> }</tbody></table></div></div><div class="card-footer d-flex justify-content-between align-items-center"><div class="text-start"><button class="btn btn-primary m-1" @onclick="() => NavigationService.RedirectToGames()"><i class="bi bi-arrow-90deg-left"></i> Retour</button></div><div class="text-end"><button type="submit" class="btn btn-primary" id="save-game"> @if (IsLoading) {<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span><span class="ms-2">Chargement...</span> } else { @Action }</button></div></div></div></EditForm>@code { [Parameter] public int Id { get; set; } bool Success; public GameDto Game { get; set; } = new GameDto() { Id = 0, Players = new List<PlayerDto>(), GameParcours = new List<GameParcoursDto>(), Name = string.Empty }; public string Action { get; set; } = string.Empty; private bool IsLoading; string Message; private List<ParcoursDto> ParcoursSelected = new(); private List<int> ParcoursLoading { get; set; } = new(); private List<string> PlayersLoading { get; set; } = new(); private PlayerDto PlayerSelected { get; set; } = new(); private List<PlayerDto> PlayersSelected = new(); public List<GameParcoursDto> GameParcours { get; set; } = new();protected override async Task OnInitializedAsync(){ try { await Task.Delay(1); if (Id != 0) { Game = await GameService.GetAsync(Id); if (Game == null) { await Creating(); } else { Action = "Modifier"; ParcoursSelected = Game.GameParcours.Select(gp => gp.Parcours).ToList(); PlayersSelected = Game.Players.ToList(); StateHasChanged(); } } else { await Creating(); } SetGameParcours(); } catch (Exception ex) when (ex is NotAuthorizeException || ex is NotConnectedException) { Message = ex.Message; Success = false; } catch (Exception ex) { Logger.LogError(ex.Message); Message = "Une erreur inattendue s'est produite."; Success = false; }}My goal is to have stable test and I do not know why this test fail a lot when I run all my test. Sometimes it pass. I wonder if I do not miss something with bunit or anything else. Let me know.