Gérer le warning "Cannot convert null literal to non-nullable reference type" avec Moq

Quand on utilise Moq avec de vieux projets qui migrent de .net Framework vers .net, il y a un petit Warning qui devient vite irritant :

Warning CS8625 Cannot convert null literal to non-nullable reference type.

Celui-ci se produit quand une méthode doit retourner null.

Voici un exemple d'interface avec une opération asynchrone (histoire de reproduire un cas proche de la réalité).


public interface IMyRepository {
  ValueTask<MaClass?> MethodeReturnMaClassNullableAsync(...);
}

Pour utiliser Moq, il faut ajouter un Cast en plus du ValueTask.FromResult.


var repository = new Mock<IMyRepository>();
repository
  .Setup(c => c.MethodeReturnMaClassNullableAsync(...))
  .Returns(ValueTask.FromResult((MaClass?)null));

Toute implémentation sans le Cast et le ValueTask.FromResult feront apparaitre un Waring. Cette écriture n'est pas nouvelle, mais il semble qu'elle perturbe encore nombre de développeurs.

Jérémy Jeanson

Peut-on effectuer la mise à jour d'un agent de build en pleine journée ?

Voici une petite question qui peut perturber les administrateurs d’agent hébergés on-premise. La réponse est très simple : Oui, on peut demander la mise à jour des agents de build / déploiement en pleine journée.

La demande de mise à jour provoque la planification de celle-ci. Malheureusement, cette planification n’apparait pas dans la liste des jobs en attente.

Si un agent est occupé par une build ou un déploiement, il finit son travail. La mise à jour s'effectue ensuite.

Jérémy Jeanson

Le GC de .net 8 est parti pour être fun. Mais est-ce suffisant ?

Dynamically Adapting To Application Sizes (DATAS), voici un nom auquel il va falloir s’adapter. IL s’agit d’une nouvelle fonctionnalité du GC introduite avec .net 8.

Vous trouverez ici un très bel article décrivant le fonctionnement de DATAS, et quelques indicateurs sur le gain de performances obtenu (merci à Laurent de me l’avoir fait connaitre).

Dans les faits, il faudra attendre la RTM de .net 8 pour se faire une idée de l’implémentation définitive. Sur le principe, cette fonctionnalité va permettre une gestion dynamique du nombre de heaps (augmentation, et diminution). L’augmentation devrait permettre d’accélérer les allocations. La diminution devrait permettre de réduire la consommation globale de l’application.

Depuis que j’ai entendu parler de DATAS, je suis emballé. J’ai cependant un petit regret. La configuration est minimale. Un simple switch on / off. J’aurais aimé disposer d’un contrôle sur les nombres min / max de heap, ou une option pour anticiper les besoins en mémoire.

Ne vous méprenez pas, DATAS est une très bonne chose. Il me semble cependant que cette fonctionnalité devait initialement aller un peu plus loin. Un peu de contrôle n’aurait pas été désagréable ;)

Jérémy Jeanson

Selon Azure Pipeline, .net standard 2 ne serait pas compatible avec .net framework 4.8 ???

Voici une nouvelle plaisanterie d’Azure DevOps (il est très taquin aujourd'hui). Lors d’une build Azure Pipeline, le log fait remonter une erreur étrange : Un projet .net framework 4.8 n’aurait pas le droit de référencer un package nuget .net standard 2.

Bien évidemment, si l’on regarde la documentation, ceci est faux. Pourquoi Azure Pipeline se tromperait-il sur un sujet aussi simple ?

La raison ne se cache pas du côté, Azure DevOps. Le problème est lié à l’outillage installé sur le serveur de build. Celui-ci n’utilise pas forcément une version de nuget compatible avec .net standard. La solution la plus simple consiste donc à ajouter une tâche NuGetToolInstaller@1. Celle-ci se chargera d’installer la dernière version de nuget, ce qui résout le problème, et évitera les suivants ;).

Ce qui donne :


steps:
  - task: NuGetToolInstaller@1      
  - task: NuGetCommand@2
    displayName: 'NuGet restore'
    inputs:
      restoreSolution: $(solution)
      command: restore
          
  - task: DotNetCoreCLI@2
    displayName: 'Compilation'
    inputs:
      command: build
      projects: '$(solution)'
      arguments: '--configuration $(buildConfiguration)'
Jérémy Jeanson

Que faire quand Azure Pipeline dit qu’il est impossible de charger l'index nuget d’Azure DevOps ?

Voici une situation des plus cocasses. Des projets utilisent des packages nuget hébergés dans Azure DevOps. Lors de la build, Azure Pipeline indique qu’il est incapable de charger l’index nuget d'Azure Artefacts.

Au premier abord, on peut penser à un problème de droits d’accès. Mais il n’en est rien. Ou du moins le problème est un peu plus tordu que cela. Les pipelines ont bien le droit d’accéder à repository Azure Artefacts.

Le problème se trouve en fait au niveau de la tâche qui cherche à restaurer les packages. Comme beaucoup, j’utilisais DotNetCoreCLI@2. En temps normal, pas de problèmes. La tâche restaure les packages, et compile les projets. Mais, j’avais beau lui indiquer explicitement la configuration nuget, ou l’URL du repository, rien n’y faisait.

Et puis j’ai eu l’idée un peu folle de faire à l’ancienne. Comme pour les vieilles solutions .net Framework. Pour ceux qui n’ont pas connu cette douce époque. La tâche VSBuild@1 doit être précédée d’une tâche NuGetCommand@2 avec l'option restore.

Si on applique le même principe, on s’aperçoit vite que NuGetCommand@2 accède aux packages et à l’index d’Azure Artefacts. La restauration et la build deviennent donc possibles.

Ce qui donne :


steps:
  - task: NuGetToolInstaller@1      
  - task: NuGetCommand@2
    displayName: 'NuGet restore'
    inputs:
      restoreSolution: $(solution)
      command: restore
      feedsToUse: config
      nugetConfigPath: '$(system.defaultworkingdirectory)/Sources/nuget.config'
          
  - task: DotNetCoreCLI@2
    displayName: 'Compilation'
    inputs:
      command: build
      projects: $(solution)
      arguments: '--configuration $(buildConfiguration)'


Note : La tâche NuGetCommand@2 suffit à avoir une solution fonctionnelle. Cependant, j’ajoute une tâche NuGetToolInstaller@1 afin d’éviter d’autres problèmes. Ceux-ci feront l’objet d’un second article.

Jérémy Jeanson