首页 / C# / c#-单元测试仅在构建服务器上运行时失败
c#-单元测试仅在构建服务器上运行时失败
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c#-单元测试仅在构建服务器上运行时失败,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4770字,纯文字阅读大概需要7分钟。
内容图文
![c#-单元测试仅在构建服务器上运行时失败](/upload/InfoBanner/zyjiaocheng/664/b0b3b2ee5dbf42b3a3162cc3da654de5.jpg)
为了帮助进行单元测试,我们将DateTime类包装在委托中,以便可以在单元测试中覆盖DateTime.Now.
public static class SystemTime
{
#region Static Fields
public static Func<DateTime> Now = () => DateTime.Now;
#endregion
}
这是在xunit单元测试中使用它的示例:
[Fact]
public void it_should_update_the_last_accessed_timestamp_on_an_entry()
{
// Arrange
var service = this.CreateClassUnderTest();
var expectedTimestamp = SystemTime.Now();
SystemTime.Now = () => expectedTimestamp;
// Act
service.UpdateLastAccessedTimestamp(this._testEntry);
// Assert
Assert.Equal(expectedTimestamp, this._testEntry.LastAccessedOn);
}
该测试在本地运行良好,但是由于Assert语句中的日期时间不同,因此在我们的构建服务器上失败了.
考虑到DateTime是通过上述委托包装器模拟的,因此我很难思考为什么它会失败的原因.我已经验证了UpdateLastAccessedTimestamp方法的实现没有问题,并且在本地运行时该测试通过了.
不幸的是,我无法在构建服务器上对其进行调试.有什么想法为什么它只有在构建服务器上运行时才会失败?
请注意,UpdateLastAccessedTimestamp的实现如下:
public void UpdateLastAccessedTimestamp(Entry entry)
{
entry.LastAccessedOn = SystemTime.Now();
this._unitOfWork.Entries.Update(entry);
this._unitOfWork.Save();
}
Entry类只是一个简单的POCO类,它具有许多字段,包括LastAccessedOn字段:
public class Entry
{
public DateTime LastAccessedOn { get; set; }
//other fields that have left out to keep the example concise
}
解决方法:
您的问题可能是由于使用静态SystemTime进行了多个单元测试.例如,如果您要进行以下操作:
单元测试1
[Fact]
public void it_should_update_the_last_accessed_timestamp_on_an_entry()
{
// Arrange
var service = this.CreateClassUnderTest();
var expectedTimestamp = SystemTime.Now();
SystemTime.Now = () => expectedTimestamp;
// Act
service.UpdateLastAccessedTimestamp(this._testEntry);
// Assert
Assert.Equal(expectedTimestamp, this._testEntry.LastAccessedOn);
}
public void UpdateLastAccessedTimestamp(Entry entry)
{
entry.LastAccessedOn = SystemTime.Now();
this._unitOfWork.Entries.Update(entry);
this._unitOfWork.Save();
}
单元测试2
[Fact]
public void do_something_different
{
SystemTime.Now = () => DateTime.Now;
}
因此,假设单元测试2(全部)在单元测试1的两行之间触发:
SystemTime.Now = () => expectedTimestamp;
// Unit test 2 starts execution here
// Act
service.UpdateLastAccessedTimestamp(this._testEntry);
如果发生这种情况,那么您的UpdateLastAccessedTimestamp将(不必)具有您在SystemTime上设置的预期DateTime值.Now=()=> ExpectedTimestamp ;,因为另一个测试已经覆盖了您从单元测试1中提供的功能.
这就是为什么我认为您最好将DateTime作为参数传递,或者使用可注入的datetime更好:
/// <summary>
/// Injectable DateTime interface, should be used to ensure date specific logic is more testable
/// </summary>
public interface IDateTime
{
/// <summary>
/// Current Data time
/// </summary>
DateTime Now { get; }
}
/// <summary>
/// DateTime.Now - use as concrete implementation
/// </summary>
public class SystemDateTime : IDateTime
{
/// <summary>
/// DateTime.Now
/// </summary>
public DateTime Now { get { return DateTime.Now; } }
}
/// <summary>
/// DateTime - used to unit testing functionality around DateTime.Now (externalizes dependency on DateTime.Now
/// </summary>
public class MockSystemDateTime : IDateTime
{
private readonly DateTime MockedDateTime;
/// <summary>
/// Take in mocked DateTime for use in testing
/// </summary>
/// <param name="mockedDateTime"></param>
public MockSystemDateTime(DateTime mockedDateTime)
{
this.MockedDateTime = mockedDateTime;
}
/// <summary>
/// DateTime passed from constructor
/// </summary>
public DateTime Now { get { return MockedDateTime; } }
}
在这种情况下,您的服务类可能会发生如下变化:
public class Service
{
public Service() { }
public void UpdateLastAccessedTimestamp(Entry entry)
{
entry.LastAccessedOn = SystemTime.Now();
this._unitOfWork.Entries.Update(entry);
this._unitOfWork.Save();
}
}
对此:
public class Service
{
private readonly IDateTime _iDateTime;
public Service(IDateTime iDateTime)
{
if (iDateTime == null)
throw new ArgumentNullException(nameof(iDateTime));
// or you could new up the concrete implementation of SystemDateTime if not provided
_iDateTime = iDateTime;
}
public void UpdateLastAccessedTimestamp(Entry entry)
{
entry.LastAccessedOn = _iDateTime.Now;
this._unitOfWork.Entries.Update(entry);
this._unitOfWork.Save();
}
}
对于服务的实际实现,您可以像(或使用IOC容器)进行更新:
Service service = new Service(new SystemDateTime());
为了进行测试,您可以使用模拟框架,也可以使用Mock类:
Service service = new Service(new MockDateTime(new DateTime(2000, 1, 1)));
您的单元测试可能变为:
[Fact]
public void it_should_update_the_last_accessed_timestamp_on_an_entry()
{
// Arrange
MockDateTime mockDateTime = new MockDateTime(new DateTime 2000, 1, 1);
var service = this.CreateClassUnderTest(mockDateTime);
// Act
service.UpdateLastAccessedTimestamp(this._testEntry);
// Assert
Assert.Equal(mockDateTime.Now, this._testEntry.LastAccessedOn);
}
内容总结
以上是互联网集市为您收集整理的c#-单元测试仅在构建服务器上运行时失败全部内容,希望文章能够帮你解决c#-单元测试仅在构建服务器上运行时失败所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。