Как вы издеваетесь над ILogger LogInformation - PullRequest
0 голосов
/ 08 октября 2018

У меня есть класс, который получает ILogger, и я хочу смоделировать вызовы LogInformation, но это метод расширения.Как мне сделать соответствующий вызов для установки?

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

ILogger обычно используется через методы расширения, LogWarning, LogError и т. Д.

В моем случае меня заинтересовал метод LogWarning, который после просмотра кода вызывает метод Log из ILogger.Для того, чтобы поиздеваться над Moq, вот что я в итоге сделал:

 var list = new List<string>();
            var logger = new Mock<ILogger>();
            logger
                .Setup(l => l.Log<FormattedLogValues>(LogLevel.Warning, It.IsAny<EventId>(), It.IsAny<FormattedLogValues>(), It.IsAny<Exception>(), It.IsAny<Func<FormattedLogValues, Exception, string>>()))
                .Callback(
                delegate (LogLevel logLevel, EventId eventId, FormattedLogValues state, Exception exception, Func<FormattedLogValues, Exception, string> formatter)
                {
                    list.Add(state.ToString());
                });
0 голосов
/ 26 февраля 2019

Это обходной путь для Moq (v4.10.1) framework.

public static class TestHelper
{ 

    public static Mock<ILogger<T>> GetMockedLoggerWithAutoSetup<T>()
    {
        var logger = new Mock<ILogger<T>>();

        logger.Setup<object>(x => x.Log(
       It.IsAny<LogLevel>(),
       It.IsAny<EventId>(),
       It.IsAny<object>(),
       It.IsAny<Exception>(),
       It.IsAny<Func<object, Exception, string>>()));

        return logger;
    }

    public static void VerifyLogMessage<T>(Mock<ILogger<T>> mockedLogger, LogLevel logLevel, Func<string, bool> predicate, Func<Times> times)
    {
        mockedLogger.Verify(x => x.Log(logLevel, 0, It.Is<object>(p => predicate(p.ToString())), null, It.IsAny<Func<object, Exception, string>>()), times);
    }
}

-

public class Dummy
{

}

[Fact]
public void Should_Mock_Logger()
{
    var logger = TestHelper.GetMockedLoggerWithAutoSetup<Dummy>();
    logger.Object.LogInformation("test");
    TestHelper.VerifyLogMessage<Dummy>(logger, LogLevel.Information, msg => msg == "test", Times.Once);
}

-

Дело в том, что

Если бы я выбрал для logger.Setup() любой другой <TCustom>, чем <object>, на шаге Verify произойдет сбой, сказав, что 0 вызовов были сделаны дляx.Log<TCustom> и показ звонка на x.Log<object>.Поэтому я настроил мой универсальный логгер на использование метода Log<object>(..).

0 голосов
/ 09 октября 2018

//Hi you can find the code with Moq.dll from the below link
http://www.dotnetsurfers.com/blog/2010/04/02/getting-started-with-mocking-part-2-using-moq

//Here Define Interfaces with models Logger,Product and ShoppingCart

using System;
using System.Diagnostics;
using System.IO;

namespace MOQSamples.Model
{
    public interface ILogger
    {
        void Log(string text);
    }

    public class Logger : ILogger
    {
        public void Log(string text)
        {
            TextWriter tw = new StreamWriter(@"C:\temp\moq.log",false);
            tw.WriteLine(text);
            tw.Close();
        }
    }
}




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MOQSamples.Model
{
    public class ShoppingCart
    {
        public ShoppingCart(ILogger logger)
        {
            this._logger = logger;
        }

        private ILogger _logger;
        public decimal Total { get; set; }

        public void AddProduct(IProduct product)
        {
            Total = Total + product.Price;
            if (_logger != null)
                _logger.Log(String.Format("Product {0} has been added.",product.Name));
        }
    }
}





using System;
using System.Data.SqlClient;

namespace MOQSamples.Model
{
    public interface IProduct
    {
        string Name { get; set; }

        decimal Price { get; set; }

        string GetProductCategory();

    }

    public class Product : IProduct
    {
        public int ID {get;set;}

        public string Name {get; set;}
        public decimal Price
        {
            get { return GetPriceFromDatabase(); }
            set { throw new NotImplementedException(); }
        }

        public string GetProductCategory()
        {
            throw new NotImplementedException();
        }

        private decimal GetPriceFromDatabase()
        {
            #region Retrieve Price from DB

            var conn = new SqlConnection("Server=WIN-V0L52BJTJS6; Database=MOQ; Integrated Security=SSPI;");
            var query = "select Price from Product where ID =" + ID;
            var cmd = new SqlCommand(query, conn);
            conn.Open();
            var price = (decimal)cmd.ExecuteScalar();
            conn.Close();
            return price;

            #endregion
        }
    }
}

//testing the logger 


using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Moq.Language;
using MOQSamples.Model;


namespace MOQSamples.Test
{
    [TestClass]
    public class MOQDemoTests
    {
        private Mock<IProduct> _mockProduct;
        private Mock<ILogger> _mockLogger;

        [TestInitialize]
        public void InitializeTests()
        {
            _mockProduct = new Mock<IProduct>();
            _mockLogger = new Mock<ILogger>();
        }

        [TestMethod]
        public void Demo_Setup_Method()
        {
            //Show how a method call can be mocked and return fake data
            _mockProduct.Setup(m => m.GetProductCategory()).Returns("Test Category");
            Console.WriteLine(_mockProduct.Object.GetProductCategory());
        
        }

        [TestMethod]
        public void Demo_Setup_PropertyGet()
        {
            //Show how a property can be mocked and return fake data
            _mockProduct.SetupGet(m => m.Name).Returns("Product 1");
            Console.WriteLine(_mockProduct.Object.Name);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Demo_Setup_ThrowException()
        {
            //show how a mock can be used to throw exception
            _mockLogger.Setup(m => m.Log(It.Is<string>(p => p == null))).
                Throws(new ArgumentNullException());
            _mockLogger.Object.Log(null);
        }

        [TestMethod]
        public void Demo_Validate_Params()
        {
            //show how mock can validate parameters
            _mockLogger.Setup(m => m.Log(It.IsRegex("[1-9]+"))).
                Callback(() => Console.WriteLine("Numbers passed"));
            _mockLogger.Object.Log("123");
        }

        [TestMethod]
        public void Demo_Verify_Interactions()
        {
            _mockLogger.Object.Log("test");
            _mockLogger.Verify(m => m.Log(It.Is<string>(s=>s=="test")),Times.Once());
        }

        [TestMethod]
        public void Demo_Setup_CallBack()
        {

            //show how a mock can be used to invoke a callback
            int counter = 0;
            _mockLogger.Setup(m => m.Log(It.IsAny<String>())).Callback(() => counter++);
            _mockLogger.Object.Log("test");
            _mockLogger.Object.Log("test2");

            Console.WriteLine("Counter is " + counter);
        }

    }
}
...