[英]Unit testing DateTime controller using NUnit
I am creating a React / .NET Core project and one of the pages displays the current date and time. 我正在创建一个React / .NET Core项目,其中一个页面显示当前的日期和时间。 My controller class is as follows:
我的控制器类如下:
namespace TestingReactDotNet.Controllers {
[Route ("api/[controller]")]
public class DayTodayController : Controller {
[HttpGet, Route ("GetDate")]
public string GetDate () {
var info = $"Today is {DateTime.Now.ToString("dddd, dd MMMM yyyy")} and the time is {DateTime.Now.ToString("hh:mm tt")}";
return info;
}
}
}
I am trying to unit test this and mock the date and time but am struggling to do this (I have looked at other Stack Overflow questions and Googled but I am still having trouble). 我正在尝试对此进行单元测试并模拟日期和时间,但我正在努力做到这一点(我已经查看了其他Stack Overflow问题和谷歌搜索,但我仍然遇到麻烦)。 I originally wanted to use
Moq
but it seems that this may not be possible? 我原本想使用
Moq
但似乎这可能不可能?
Here is what I have so far for my test: 这是我到目前为止测试的内容:
namespace TestingReactDotNetTests
{
public class DayTodayTests
{
[Test]
public void ReturnsDateAndTime()
{
var controller = new DayTodayController();
string result = controller.GetDate();
string expected = "Today is Tuesday 27 August 2019 and the time is 10:00";
Assert.AreEqual(expected, result);
}
}
}
My question is - how can I set the date and time so that when DateTime.Now
is called in the string, it isn't the current date and time? 我的问题是 - 如何设置日期和时间,以便在字符串中调用
DateTime.Now
时,它不是当前的日期和时间?
The usual way to achieve this is to inject a date/time provider in the constructor of the object you are testing. 实现此目的的常用方法是在要测试的对象的构造函数中注入日期/时间提供程序。 For example:
例如:
public interface IDateTimeProvider
{
DateTime Now();
}
and a concrete implementation of that interface: 以及该接口的具体实现:
public class DateTimeProvider : IDateTimeProvider
{
public DateTime Now()
{
return Datetime.Now;
}
}
You need to add IDateTimeProvider
to the DI container, 您需要将
IDateTimeProvider
添加到DI容器中,
something like 就像是
services.AddSingleton<IDateTimeProvider, DateTimeProvider>();
but it depends on how you have set it up, which framework you are using etc. 但这取决于你如何设置,你正在使用哪个框架等。
You controller would change to something like this: 您的控制器将更改为以下内容:
[Route ("api/[controller]")]
public class DayTodayController : Controller
{
private readonly IDateTimeProvider _dateTimeProvider;
public DayTodayController(IDateTimeProvider dateTimeProvider)
{
_dateTimeProvider = dateTimeProvider;
}
[HttpGet, Route ("GetDate")]
public string GetDate () {
var dateTime = _dateTimeProvider.Now();
var info = $"Today is {dateTime.ToString("dddd, dd MMMM yyyy")} and the time is {dateTime.ToString("hh:mm tt")}";
return info;
}
}
Note the assignment of the DateTime to a variable. 请注意将DateTime分配给变量。 Calling
DateTime.Now
multiple times will give different values, so you would want to operate on one instance to get the desired behavior. 多次调用
DateTime.Now
将给出不同的值,因此您希望在一个实例上操作以获得所需的行为。
And now you can test with a non-brittle mocked implementation of the interface: 现在,您可以使用非脆弱的模拟实现接口进行测试:
public class DayTodayTests
{
[Test]
public void ReturnsDateAndTime()
{
//Arrange
var mockedDateTimeProvider = new Mock<IDateTimeProvider>();
mockedDateTimeProvider.Setup(dtp => dtp.Now()).Returns(new DateTime(2019, 8, 27, 10, 0, 0));
var controller = new DayTodayController(mockedDateTimeProvider.Object);
//Act
string result = controller.GetDate();
//Assert
string expected = "Today is Tuesday 27 August 2019 and the time is 10:00 AM";
Assert.AreEqual(expected, result);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.