System.ArgumentNullException:单元测试中的值不能为空 - C#
System.ArgumentNullException : Value cannot be null in unit test - C#
我在 运行 单元测试时遇到此错误:
Error Message:
System.ArgumentNullException : Value cannot be null.
Parameter name: logger
而且我也收到了这个警告:
Field 'OrderControllerTest._logger' is never assigned to, and will always have its default value null
有没有办法让记录器静音或测试它?
对编程还是个新手,渴望学习。已经为此苦苦挣扎了很长时间。感谢您的帮助和指导。
使用堆栈跟踪更新
Stack Trace:
at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, String message, Object[] args)
at Microsoft.Extensions.Logging.LoggerExtensions.LogError(ILogger logger, Exception exception, String message, Object[] args)
at Project.Controllers.OrderController.CustomerOrders(String customerId) in C:\projects\Project\Controllers\OrderController.cs:line 34
at Tests.OrderControllerTest.AllOrdersForCustomer() in C:\projects\UnitTests\Project.Service.Tests\OrderControllerTest.cs:line 74
我目前拥有的:
OrderControllerTest.cs:
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Project.Models;
using Project.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace Tests
{
[TestFixture]
public class OrderControllerTest
{
ILogger<OrderController> _logger;
public OrderControllerTest()
{
}
[Test]
public void AllOrdersForCustomer()
{
// Arrange
var controller = new OrderController(_logger);
var expectedResult = new List<Order>();
var oneOrder = new Order()
{
orderId = 228,
product= "Jeans",
status = "Ready for shipping",
price= 20$
};
var twoOrder = new Order()
{
caseId = 512,
creditorName = "Basketball",
status = "Shipped",
totalOpenBalance = 30$
};
expectedResult.Add(oneOrder);
expectedResult.Add(twoOrder);
// Act
var actionResult = controller.CustomerOrders("1243");
var result = (List<Order>)actionResult;
// Assert
for (var i = 0; i < result.Count; i++)
{
CollectionAssert.AreEqual(expectedResult, result);
}
}
}
OrderController.cs:
using System;
using System.Collections.Generic;
using Project.Models;
using Project.Repositories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace Project.Controllers
{
public class OrderController : Controller
{
ILogger<OrderController> _logger;
public OrderController(ILogger<OrderController> logger)
{
_logger = logger;
}
[HttpGet("customers/{customerId}/orders")]
public List<Order> CustomerOrders(string customerId)
{
try
{
return OrderRepository.AllOrders(customerId);
}
catch (Exception ex)
{
_logger.LogError(ex, "Cant retrieve no orders.");
return null;
}
}
}
}
ILogger<OrderController> _logger;
public OrderControllerTest()
{
_logger = new Mock<ILogger<OrderController>>().Object;
}
OrderRepository.cs:
public static List<Order> AllOrders(string customerId)
{
var orderlist = new List<Order>();
if (Order!=null && Order.Count>0)
{
if (Order.TryGetValue(customerId, out orderlist))
return orderlist;
}
return FromDB(customerId);
}
在 "OrderControllerTest" class 的构造函数中,您需要创建 ILogger 接口的模拟。 Logger 是您的 OrderController 的依赖项,您不想在控制器的单元测试中测试它的功能。
有很多好的模拟框架。我更喜欢 Moq 但还有很多其他的。然后您需要模拟您的 OrderController 正在使用的方法。
最小起订量示例:
using ...
using Moq;
namespace Tests
{
[TestFixture]
public class OrderControllerTest
{
public OrderControllerTest()
{
var mockLogger = new Mock<ILogger<OrderController>>();
mockLogger.Setup( x => x.LogError( It.IsAny<Exception>(), It.IsAny<string>() );
_logger = mockLogger.Object;
}
...
}
}
假设您已从 EL MOJO 获取输入,您需要在测试中使用 Moq 初始化 ILogger:
Mock<ILogger<OrderController>> _logger;
public OrderControllerTest()
{
_logger = new Mock<ILogger<OrderController>>();
_logger.Setup(m => m.LogError(It.IsAny<Exception>(), It.IsAny<string>()));
}
现在您应该使用以下内容初始化您的控制器:
var controller = new OrderController(_logger.Object);
我在 运行 单元测试时遇到此错误:
Error Message:
System.ArgumentNullException : Value cannot be null.
Parameter name: logger
而且我也收到了这个警告:
Field 'OrderControllerTest._logger' is never assigned to, and will always have its default value null
有没有办法让记录器静音或测试它?
对编程还是个新手,渴望学习。已经为此苦苦挣扎了很长时间。感谢您的帮助和指导。
使用堆栈跟踪更新
Stack Trace:
at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, String message, Object[] args)
at Microsoft.Extensions.Logging.LoggerExtensions.LogError(ILogger logger, Exception exception, String message, Object[] args)
at Project.Controllers.OrderController.CustomerOrders(String customerId) in C:\projects\Project\Controllers\OrderController.cs:line 34
at Tests.OrderControllerTest.AllOrdersForCustomer() in C:\projects\UnitTests\Project.Service.Tests\OrderControllerTest.cs:line 74
我目前拥有的:
OrderControllerTest.cs:
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Project.Models;
using Project.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace Tests
{
[TestFixture]
public class OrderControllerTest
{
ILogger<OrderController> _logger;
public OrderControllerTest()
{
}
[Test]
public void AllOrdersForCustomer()
{
// Arrange
var controller = new OrderController(_logger);
var expectedResult = new List<Order>();
var oneOrder = new Order()
{
orderId = 228,
product= "Jeans",
status = "Ready for shipping",
price= 20$
};
var twoOrder = new Order()
{
caseId = 512,
creditorName = "Basketball",
status = "Shipped",
totalOpenBalance = 30$
};
expectedResult.Add(oneOrder);
expectedResult.Add(twoOrder);
// Act
var actionResult = controller.CustomerOrders("1243");
var result = (List<Order>)actionResult;
// Assert
for (var i = 0; i < result.Count; i++)
{
CollectionAssert.AreEqual(expectedResult, result);
}
}
}
OrderController.cs:
using System;
using System.Collections.Generic;
using Project.Models;
using Project.Repositories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace Project.Controllers
{
public class OrderController : Controller
{
ILogger<OrderController> _logger;
public OrderController(ILogger<OrderController> logger)
{
_logger = logger;
}
[HttpGet("customers/{customerId}/orders")]
public List<Order> CustomerOrders(string customerId)
{
try
{
return OrderRepository.AllOrders(customerId);
}
catch (Exception ex)
{
_logger.LogError(ex, "Cant retrieve no orders.");
return null;
}
}
}
}
ILogger<OrderController> _logger;
public OrderControllerTest()
{
_logger = new Mock<ILogger<OrderController>>().Object;
}
OrderRepository.cs:
public static List<Order> AllOrders(string customerId)
{
var orderlist = new List<Order>();
if (Order!=null && Order.Count>0)
{
if (Order.TryGetValue(customerId, out orderlist))
return orderlist;
}
return FromDB(customerId);
}
在 "OrderControllerTest" class 的构造函数中,您需要创建 ILogger 接口的模拟。 Logger 是您的 OrderController 的依赖项,您不想在控制器的单元测试中测试它的功能。
有很多好的模拟框架。我更喜欢 Moq 但还有很多其他的。然后您需要模拟您的 OrderController 正在使用的方法。
最小起订量示例:
using ...
using Moq;
namespace Tests
{
[TestFixture]
public class OrderControllerTest
{
public OrderControllerTest()
{
var mockLogger = new Mock<ILogger<OrderController>>();
mockLogger.Setup( x => x.LogError( It.IsAny<Exception>(), It.IsAny<string>() );
_logger = mockLogger.Object;
}
...
}
}
假设您已从 EL MOJO 获取输入,您需要在测试中使用 Moq 初始化 ILogger:
Mock<ILogger<OrderController>> _logger;
public OrderControllerTest()
{
_logger = new Mock<ILogger<OrderController>>();
_logger.Setup(m => m.LogError(It.IsAny<Exception>(), It.IsAny<string>()));
}
现在您应该使用以下内容初始化您的控制器:
var controller = new OrderController(_logger.Object);