C# - 使用 Guid 参数引发事件的单元测试方法
C# - Unit test method that raises event with Guid argument
我正在尝试弄清楚如何测试这种情况,但一无所获。
我有一个侦听器服务,当在邮槽中检测到文件时会触发以下事件:
IEventDispatcher _dispatcher;
IListener _mailslotListener;
public Service (IEventDispatcher dispatcher, IMailslotListener mailslotListener) {
_dispatcher = dispatcher;
_mailslotListener = mailslotListener;
}
public async void _Listener_OnFileDetected(object sender, MailslotArgs) {
string filePath = args.Message;
Directory.CreateDirectory(TempLocation);
FileId = Guid.NewGuid();
string tempPath = Path.Combine(TempLocation, FileId.ToString());
File.Move(filePath, tempPath);
await _dispatcher.DispatchEvent("documentPrinted", FileId);
}
这会将传入的文件移动到一个临时位置并使用 Guid 重命名它。在我的测试中,我试图验证文件是否已成功移动,但我不确定如何访问使用并传递给 _dispatcher.DispatchEvent 调用的 Guid。
我能够验证事件是否已引发,但这是我所了解的,因为在测试中声明相等性时,随机 Guid 的值似乎是一个问题。
[Test]
public void OnFileDetected_CallsDispatchEvent()
{
Directory.CreateDirectory(tempPath);
listenerService._Listener_OnFileDetected(null, new MailslotArgs(testFilePath));
mockEventDispatcher.Verify(m => m.DispatchEvent("fileDetected",
It.IsAny<Guid>()),
Times.Once);
}
这是 static
初始值设定项的典型问题。它被称为 DateTime.Now
变体,但结果是相同的。
问题是,由于它是静态的,因此很难模拟该方法的输出。
由于它是在实现中使用的,因此 GUID 的结果保存在其中,并且没有简单的方法来访问它。
一种常见的方法是创建一个包装器 class + 接口,以公开 Guid.NewGuid()
方法。
使用这种方法,您可以完全控制 Guid 生成 - 您只需要使用适当的 class.
//The interface
public interface IGuidGenerator
{
Guid NewGuid();
}
//Use in the application
public class GuidGenerator: IGuidGenerator
{
public Guid NewGuid()
{
return Guid.NewGuid();
}
}
//Use in the test scenario
public class TestGuidGenerator: IGuidGenerator
{
public Guid NewGuid()
{
return new Guid("dddddddd-dddd-dddd-dddd-dddddddddddd");
}
}
如果您使用的是 IoC 框架,只需注册接口和 class,然后将生成器传递给服务即可:
public Service (IEventDispatcher dispatcher,
IMailslotListener mailslotListener,
IGuidGenerator guidGenerator)
{
_dispatcher = dispatcher;
_mailslotListener = mailslotListener;
_guidGenerator = guidGenerator;
}
DateTime.Now
变体,其实是常用作面试题。
这里有更多关于这个主题的内容:https://dvoituron.com/2020/01/22/UnitTest-DateTime/
我正在尝试弄清楚如何测试这种情况,但一无所获。
我有一个侦听器服务,当在邮槽中检测到文件时会触发以下事件:
IEventDispatcher _dispatcher;
IListener _mailslotListener;
public Service (IEventDispatcher dispatcher, IMailslotListener mailslotListener) {
_dispatcher = dispatcher;
_mailslotListener = mailslotListener;
}
public async void _Listener_OnFileDetected(object sender, MailslotArgs) {
string filePath = args.Message;
Directory.CreateDirectory(TempLocation);
FileId = Guid.NewGuid();
string tempPath = Path.Combine(TempLocation, FileId.ToString());
File.Move(filePath, tempPath);
await _dispatcher.DispatchEvent("documentPrinted", FileId);
}
这会将传入的文件移动到一个临时位置并使用 Guid 重命名它。在我的测试中,我试图验证文件是否已成功移动,但我不确定如何访问使用并传递给 _dispatcher.DispatchEvent 调用的 Guid。
我能够验证事件是否已引发,但这是我所了解的,因为在测试中声明相等性时,随机 Guid 的值似乎是一个问题。
[Test]
public void OnFileDetected_CallsDispatchEvent()
{
Directory.CreateDirectory(tempPath);
listenerService._Listener_OnFileDetected(null, new MailslotArgs(testFilePath));
mockEventDispatcher.Verify(m => m.DispatchEvent("fileDetected",
It.IsAny<Guid>()),
Times.Once);
}
这是 static
初始值设定项的典型问题。它被称为 DateTime.Now
变体,但结果是相同的。
问题是,由于它是静态的,因此很难模拟该方法的输出。
由于它是在实现中使用的,因此 GUID 的结果保存在其中,并且没有简单的方法来访问它。
一种常见的方法是创建一个包装器 class + 接口,以公开 Guid.NewGuid()
方法。
使用这种方法,您可以完全控制 Guid 生成 - 您只需要使用适当的 class.
//The interface
public interface IGuidGenerator
{
Guid NewGuid();
}
//Use in the application
public class GuidGenerator: IGuidGenerator
{
public Guid NewGuid()
{
return Guid.NewGuid();
}
}
//Use in the test scenario
public class TestGuidGenerator: IGuidGenerator
{
public Guid NewGuid()
{
return new Guid("dddddddd-dddd-dddd-dddd-dddddddddddd");
}
}
如果您使用的是 IoC 框架,只需注册接口和 class,然后将生成器传递给服务即可:
public Service (IEventDispatcher dispatcher,
IMailslotListener mailslotListener,
IGuidGenerator guidGenerator)
{
_dispatcher = dispatcher;
_mailslotListener = mailslotListener;
_guidGenerator = guidGenerator;
}
DateTime.Now
变体,其实是常用作面试题。
这里有更多关于这个主题的内容:https://dvoituron.com/2020/01/22/UnitTest-DateTime/