Это мой контроллер:
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);
}
}
Как видите, у меня есть 2 зависимости: a IDAO
и a.ILogger
И это мой тестовый класс, я использую xUnit для тестирования и Moq для создания макета и заглушки, я могу DAO
легко имитировать , но с помощью ILogger
я не знаю, что делать, я просто передаю null и закомментирую вызов для входа в контроллер при запуске теста. Есть ли способ протестировать, но как-то сохранить регистратор?
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
. У него есть несколько хороших предложений в своем блоге, и я пришел со своим решением, которое, кажется, решает большинство проблем в ответе ниже .Ответы:
Просто смейтесь над ним, как и над любой другой зависимостью:
Для использования вам, вероятно, потребуется установить
Microsoft.Extensions.Logging.Abstractions
пакетILogger<T>
.Более того, вы можете создать настоящий логгер:
источник
На самом деле, я нашел
Microsoft.Extensions.Logging.Abstractions.NullLogger<>
идеальное решение. Установите пакетMicrosoft.Extensions.Logging.Abstractions
, затем следуйте примеру, чтобы настроить и использовать его:и модульный тест
источник
Используйте настраиваемый регистратор, который использует
ITestOutputHelper
(из xunit) для захвата вывода и журналов. Ниже приведен небольшой образец, который записывает только наstate
выход.Используйте его в своих юнит-тестах, например
источник
ILogger
сделает его более удобным для использования. 2) ОбъектBeginScope
не должен возвращать себя, поскольку это означает, что любые проверенные методы, которые начинают и заканчивают область действия во время выполнения, будут уничтожать регистратор. Вместо этого создайте частный «манекен» вложенный класс , который реализуетIDisposable
и возвращает экземпляр , который ( а затем удалитьIDisposable
изXunitLogger
).Для .net core 3 ответов, использующих Moq
https://stackoverflow.com/a/56728528/2164198
больше не работают из-за изменения, описанного в проблеме TState в ILogger.Log раньше был объектом, теперь FormattedLogValues
К счастью, stakx предоставил хороший обходной путь . Поэтому я публикую его в надежде, что это поможет сэкономить время другим (потребовалось время, чтобы разобраться во всем):
источник
Добавляя мои 2 цента, это вспомогательный метод расширения, обычно помещаемый в статический вспомогательный класс:
Затем вы используете его так:
И, конечно, вы можете легко расширить его, чтобы высмеять любые ожидания (например, ожидания, сообщения и т. Д.)
источник
ILogger
: gist.github.com/timabell/d71ae82c6f3eaa5df26b147f9d3842ebIt.Is<string>(s => s.Equals("A parameter is empty!"))
Это легко, поскольку другие ответы предлагают пройти имитацию
ILogger
, но внезапно становится намного более проблематичным проверить, действительно ли вызовы были сделаны в регистратор. Причина в том, что большинство вызовов на самом деле не принадлежат самомуILogger
интерфейсу.Таким образом, большинство вызовов - это методы расширения, которые вызывают единственный
Log
метод интерфейса. Причина, по-видимому, в том, что гораздо проще реализовать интерфейс, если у вас есть только одна, а не много перегрузок, которые сводятся к одному и тому же методу.Недостатком, конечно же, является то, что внезапно становится намного труднее проверить, что вызов был сделан, поскольку вызов, который вы должны проверить, сильно отличается от того, который вы сделали. Есть несколько разных подходов для решения этой проблемы, и я обнаружил, что собственные методы расширения для имитации фреймворка упростят написание.
Вот пример метода, с которым я работал
NSubstitute
:И вот как это можно использовать:
Выглядит точно так, как если бы вы использовали метод напрямую, уловка здесь в том, что наш метод расширения получает приоритет, потому что он «ближе» в пространствах имен, чем исходный, поэтому он будет использоваться вместо него.
К сожалению, это не дает 100% того, что мы хотим, а именно сообщения об ошибках не будут такими хорошими, поскольку мы проверяем не непосредственно строку, а лямбду, которая включает строку, но 95% лучше, чем ничего :) Дополнительно этот подход сделает тестовый код
PS Для Moq можно использовать подход написания методы расширения для ,
Mock<ILogger<T>>
что делаетVerify
для достижения аналогичных результатов.PPS Это больше не работает в .Net Core 3, проверьте эту ветку для более подробной информации: https://github.com/nsubstitute/NSubstitute/issues/597#issuecomment-573742574
источник
Уже упоминалось, что вы можете имитировать его, как любой другой интерфейс.
Все идет нормально.
Приятно то, что вы можете использовать его
Moq
для проверки того, что определенные вызовы были выполнены . Например, здесь я проверяю, что журнал был вызван с конкретнымException
.При использовании
Verify
суть заключается в том, чтобы делать это против реальногоLog
методаILooger
интерфейса, а не методов расширения.источник
Основываясь еще на работе @ ivan-samygin и @stakx, вот методы расширения, которые также могут соответствовать исключению и всем значениям журнала (KeyValuePairs).
Они работают (на моей машине;)) с .Net Core 3, Moq 4.13.0 и Microsoft.Extensions.Logging.Abstractions 3.1.0.
источник
А при использовании StructureMap / Lamar:
Docs:
источник
Простое создание манекена
ILogger
не очень ценно для модульного тестирования. Вы также должны убедиться, что были сделаны вызовы регистрации. Вы можете ввести имитациюILogger
с помощью Moq, но проверка вызова может быть немного сложной. В этой статье подробно рассказывается о проверке с помощью Moq.Вот очень простой пример из статьи:
Он проверяет, было ли зарегистрировано информационное сообщение. Но если мы хотим проверить более сложную информацию о сообщении, такую как шаблон сообщения и названные свойства, это становится более сложной задачей:
Я уверен, что вы могли бы сделать то же самое с другими фреймворками для фиксации, но
ILogger
интерфейс гарантирует, что это сложно.источник
Если еще актуально. Простой способ вывода журнала в тестах для .net core> = 3
источник
Используйте Telerik Just Mock, чтобы создать фиктивный экземпляр регистратора:
источник
Я попытался издеваться над этим интерфейсом Logger с помощью NSubstitute (и потерпел неудачу, потому что
Arg.Any<T>()
запрашивает параметр типа, который я не могу предоставить), но в итоге создал тестовый журнал (аналогично ответу @ jehof) следующим образом:Вы можете легко получить доступ ко всем зарегистрированным сообщениям и подтвердить все значимые параметры, предоставленные с ними.
источник