首页 / C# / c#-使用接口对后台线程进行单元测试
c#-使用接口对后台线程进行单元测试
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c#-使用接口对后台线程进行单元测试,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4290字,纯文字阅读大概需要7分钟。
内容图文
![c#-使用接口对后台线程进行单元测试](/upload/InfoBanner/zyjiaocheng/664/8cae41e529d844e690c9f93ae7803f31.jpg)
我创建了一个类SenderClass,它将从其构造函数中启动和运行后台工作程序.
RunWorker()方法运行的是while(true)循环,该循环将从队列中弹出元素,通过SendMessage()方法发送它们,并休眠一小段时间以允许将新元素添加到队列中.
问题就出在这里:如何测试从队列发送元素的方法,而又不将其暴露给使用类的人呢?
实现方式:
public class SenderClass : ISenderClass
{
private Queue<int> _myQueue = new Queue<int>();
private Thread _worker;
public SenderClass()
{
//Create a background worker
_worker = new Thread(RunWorker) {IsBackground = true};
_worker.Start();
}
private void RunWorker() //This is the background worker's method
{
while (true) //Keep it running
{
lock (_myQueue) //No fiddling from other threads
{
while (_myQueue.Count != 0) //Pop elements if found
SendMessage(_myQueue.Dequeue()); //Send the element
}
Thread.Sleep(50); //Allow new elements to be inserted
}
}
private void SendMessage(int element)
{
//This is what we want to test
}
public void AddToQueue(int element)
{
Task.Run(() => //Async method will return at ones, not slowing the caller
{
lock (_myQueue) //Lock queue to insert into it
{
_myQueue.Enqueue(element);
}
});
}
}
想要的界面:
public interface ISenderClass
{
void AddToQueue(int element);
}
测试所需的接口:
public interface ISenderClass
{
void SendMessage(int element);
void AddToQueue(int element);
}
有一个非常简单的解决方案,说由于Single Responsability Principle,我创建的类不正确,而我的类的目的不是发送消息,而是实际运行发送消息的类.
我应该拥有的是另一个类TransmittingClass,该类通过其自己的接口公开方法SendMessage(int).
这样,我可以测试该类,而SenderClass应该只通过该接口调用该方法.
但是,当前的实现方式还有哪些其他选择?
我可以使要测试的所有私有方法(全部)都具有[assembly:InternalsVisibleTo(“ MyTests”)],但是是否存在第三个选项?
解决方法:
发送消息逻辑应在具有单独接口的单独类中实现.此类应将新类作为依赖项.您可以单独测试新课程.
public interface IMessageQueue
{
void AddToQueue(int element);
}
public interface IMessageSender
{
void SendMessage(object message);
}
public class SenderClass : IMessageQueue
{
private readonly IMessageSender _sender;
public SenderClass(IMessageSender sender)
{
_sender = sender;
}
public void AddToQueue(int element)
{
/*...*/
}
private void SendMessage()
{
_sender.SendMessage(new object());
}
}
public class DummyMessageSender : IMessageSender
{
//you can use this in your test harness to check for the messages sent
public Queue<object> Messages { get; private set; }
public DummyMessageSender()
{
Messages = new Queue<object>();
}
public void SendMessage(object message)
{
Messages.Enqueue(message);
//obviously you'll need to do some locking here too
}
}
编辑
为了解决您的意见,这是使用Action< int>的实现.这使您可以在测试类中定义消息发送操作以模拟SendMessage方法,而不必担心创建另一个类. (就个人而言,我仍然更愿意显式定义类/接口).
public class SenderClass : ISenderClass
{
private Queue<int> _myQueue = new Queue<int>();
private Thread _worker;
private readonly Action<int> _senderAction;
public SenderClass()
{
_worker = new Thread(RunWorker) { IsBackground = true };
_worker.Start();
_senderAction = DefaultMessageSendingAction;
}
public SenderClass(Action<int> senderAction)
{
//Create a background worker
_worker = new Thread(RunWorker) { IsBackground = true };
_worker.Start();
_senderAction = senderAction;
}
private void RunWorker() //This is the background worker's method
{
while (true) //Keep it running
{
lock (_myQueue) //No fiddling from other threads
{
while (_myQueue.Count != 0) //Pop elements if found
SendMessage(_myQueue.Dequeue()); //Send the element
}
Thread.Sleep(50); //Allow new elements to be inserted
}
}
private void SendMessage(int element)
{
_senderAction(element);
}
private void DefaultMessageSendingAction(int item)
{
/* whatever happens during sending */
}
public void AddToQueue(int element)
{
Task.Run(() => //Async method will return at ones, not slowing the caller
{
lock (_myQueue) //Lock queue to insert into it
{
_myQueue.Enqueue(element);
}
});
}
}
public class TestClass
{
private SenderClass _sender;
private Queue<int> _messages;
[TestInitialize]
public void SetUp()
{
_messages = new Queue<int>();
_sender = new SenderClass(DummyMessageSendingAction);
}
private void DummyMessageSendingAction(int item)
{
_messages.Enqueue(item);
}
[TestMethod]
public void TestMethod1()
{
//This isn't a great test, but I think you get the idea
int message = 42;
_sender.AddToQueue(message);
Thread.Sleep(100);
CollectionAssert.Contains(_messages, 42);
}
}
内容总结
以上是互联网集市为您收集整理的c#-使用接口对后台线程进行单元测试全部内容,希望文章能够帮你解决c#-使用接口对后台线程进行单元测试所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。