Ceci est mon contrôleur:
public class BlogController : Controller
{
private IDAO<Blog> _blogDAO;
private readonly ILogger<BlogController> _logger;
public BlogController(ILogger<BlogController> logger, IDAO<Blog> blogDAO)
{
this._blogDAO = blogDAO;
this._logger = logger;
}
public IActionResult Index()
{
var blogs = this._blogDAO.GetMany();
this._logger.LogInformation("Index page say hello", new object[0]);
return View(blogs);
}
}
Comme vous pouvez le voir, j'ai 2 dépendances, une IDAO
et uneILogger
Et ceci est ma classe de test, j'utilise xUnit pour tester et Moq pour créer une maquette et un stub, je peux me moquer DAO
facilement, mais avec le ILogger
je ne sais pas quoi faire, je passe simplement null et commente l'appel pour se connecter au contrôleur lors de l'exécution du test. Existe-t-il un moyen de tester tout en conservant l'enregistreur d'une manière ou d'une autre?
public class BlogControllerTest
{
[Fact]
public void Index_ReturnAViewResult_WithAListOfBlog()
{
var mockRepo = new Mock<IDAO<Blog>>();
mockRepo.Setup(repo => repo.GetMany(null)).Returns(GetListBlog());
var controller = new BlogController(null,mockRepo.Object);
var result = controller.Index();
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<IEnumerable<Blog>>(viewResult.ViewData.Model);
Assert.Equal(2, model.Count());
}
}
ILogger
. Il a quelques bonnes suggestions dans son article de blog et je suis venu avec ma solution qui semble résoudre la plupart des problèmes dans la réponse ci-dessous .Réponses:
Il suffit de le moquer ainsi que de toute autre dépendance:
Vous devrez probablement installer le
Microsoft.Extensions.Logging.Abstractions
package à utiliserILogger<T>
.De plus, vous pouvez créer un véritable enregistreur:
la source
En fait, j'ai trouvé
Microsoft.Extensions.Logging.Abstractions.NullLogger<>
ce qui ressemble à une solution parfaite. Installez le packageMicrosoft.Extensions.Logging.Abstractions
, puis suivez l'exemple pour le configurer et l'utiliser:et test unitaire
la source
Utilisez un enregistreur personnalisé qui utilise
ITestOutputHelper
(à partir de xunit) pour capturer la sortie et les journaux. Voici un petit exemple qui n'écrit que lestate
dans la sortie.Utilisez-le dans vos unittests comme
la source
ILogger
le rendra plus largement utilisable. 2) LeBeginScope
ne doit pas se retourner, car cela signifie que toutes les méthodes testées qui commencent et terminent une portée pendant l'exécution éliminent le logger. Au lieu de cela, créer une classe imbriquée « factice » privée qui met en œuvreIDisposable
et retourner une instance de ce (puis retirezIDisposable
deXunitLogger
).Pour les réponses .net core 3 utilisant Moq
https://stackoverflow.com/a/56728528/2164198
ne fonctionnent plus en raison d'un changement décrit dans le problème TState dans ILogger.Log était autrefois un objet, maintenant FormattedLogValues
Heureusement, stakx a fourni une belle solution de contournement . Je le publie donc dans l'espoir que cela puisse faire gagner du temps aux autres (il a fallu un certain temps pour comprendre les choses):
la source
En ajoutant mes 2 cents, c'est une méthode d'extension d'assistance généralement placée dans une classe d'assistance statique:
Ensuite, vous l'utilisez comme ceci:
Et bien sûr, vous pouvez facilement l'étendre pour vous moquer de toute attente (ex: attente, message, etc.)
la source
ILogger
: gist.github.com/timabell/d71ae82c6f3eaa5df26b147f9d3842ebIt.Is<string>(s => s.Equals("A parameter is empty!"))
Il est facile, comme d'autres réponses le suggèrent, de passer des simulations
ILogger
, mais il devient soudainement beaucoup plus problématique de vérifier que des appels ont effectivement été passés à l'enregistreur. La raison en est que la plupart des appels n'appartiennent pas réellement à l'ILogger
interface elle-même.Donc, la plupart des appels sont des méthodes d'extension qui appellent la seule
Log
méthode de l'interface. La raison semble être qu'il est beaucoup plus facile de faire la mise en œuvre de l'interface si vous n'avez qu'une seule et pas beaucoup de surcharges qui se résument à la même méthode.L'inconvénient est bien sûr qu'il est soudainement beaucoup plus difficile de vérifier qu'un appel a été passé car l'appel que vous devez vérifier est très différent de l'appel que vous avez passé. Il existe différentes approches pour contourner ce problème, et j'ai constaté que les méthodes d'extension personnalisées pour le framework moqueur faciliteraient l'écriture.
Voici un exemple de méthode que j'ai conçue pour travailler
NSubstitute
:Et voici comment il peut être utilisé:
Il semble exactement que vous utilisiez la méthode directement, l'astuce ici est que notre méthode d'extension a la priorité parce qu'elle est "plus proche" dans les espaces de noms que l'original, donc elle sera utilisée à la place.
Cela ne donne malheureusement pas 100% de ce que nous voulons, à savoir que les messages d'erreur ne seront pas aussi bons, car nous ne vérifions pas directement sur une chaîne mais plutôt sur un lambda qui implique la chaîne, mais 95% c'est mieux que rien :) cette approche rendra le code de test
PS Pour Moq, on peut utiliser l'approche consistant à écrire une méthode d'extension pour le
Mock<ILogger<T>>
faireVerify
pour obtenir des résultats similaires.PPS Cela ne fonctionne plus dans .Net Core 3, consultez ce fil pour plus de détails: https://github.com/nsubstitute/NSubstitute/issues/597#issuecomment-573742574
la source
Déjà mentionné, vous pouvez vous en moquer comme n'importe quelle autre interface.
Jusqu'ici tout va bien.
Une bonne chose est que vous pouvez utiliser
Moq
pour vérifier que certains appels ont été effectués . Par exemple ici je vérifie que le journal a été appelé avec un particulierException
.Lorsque vous utilisez
Verify
le point est de le faire contre laLog
méthode réelle de l'ILooger
interface et non les méthodes d'extension.la source
En s'appuyant encore plus sur le travail de @ ivan-samygin et @stakx, voici des méthodes d'extension qui peuvent également correspondre à l'exception et à toutes les valeurs de journal (KeyValuePairs).
Ceux-ci fonctionnent (sur ma machine;)) avec .Net Core 3, Moq 4.13.0 et Microsoft.Extensions.Logging.Abstractions 3.1.0.
la source
Et lors de l'utilisation de StructureMap / Lamar:
Documents:
la source
Créer simplement un mannequin
ILogger
n'est pas très utile pour les tests unitaires. Vous devez également vérifier que les appels de journalisation ont été effectués. Vous pouvez injecter une simulationILogger
avec Moq, mais la vérification de l'appel peut être un peu délicate. Cet article approfondit la vérification avec Moq.Voici un exemple très simple de l'article:
Il vérifie qu'un message d'information a été enregistré. Mais, si nous voulons vérifier des informations plus complexes sur le message comme le modèle de message et les propriétés nommées, cela devient plus délicat:
Je suis sûr que vous pourriez faire la même chose avec d'autres frameworks moqueurs, mais l'
ILogger
interface garantit que c'est difficile.la source
Si un encore réel. Manière simple de se connecter pour générer des tests pour .net core> = 3
la source
Utilisez Telerik Just Mock pour créer une instance simulée de l'enregistreur:
la source
J'ai essayé de me moquer de cette interface Logger en utilisant NSubstitute (et j'ai échoué parce que
Arg.Any<T>()
requiert un paramètre de type, que je ne peux pas fournir), mais j'ai fini par créer un enregistreur de test (similaire à la réponse de @ jehof) de la manière suivante:Vous pouvez facilement accéder à tous les messages enregistrés et affirmer tous les paramètres significatifs fournis avec.
la source