【发布时间】:2015-12-13 14:54:56
【问题描述】:
我创建了一个类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")],但是是否存在第三个选项?
【问题讨论】:
-
假设出于测试目的您公开了
SendMessage,您将如何测试它?您不会简单地通过在其他地方接收消息来检查是否发送了消息吗? -
发送消息逻辑应该在具有单独接口的单独类中实现。此类应将新类作为依赖项。您可以单独测试其他类。
-
我将其添加为解决方案@axlj - 谢谢。
标签: c# multithreading unit-testing interface backgroundworker