首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用[ UnitTesting ]通过UnitTesting创建和启动TCP服务器?

如何使用[ UnitTesting ]通过UnitTesting创建和启动TCP服务器?
EN

Stack Overflow用户
提问于 2016-01-04 18:56:22
回答 2查看 902关注 0票数 0

我正在做的是以计算程序的形式使用TCP客户端到服务器。"client“输入一个数学命令和两个数字,服务器为他执行计算并返回一个结果(exp )。加5 5;结果是10)。要做到这一点,服务器需要启动并运行,然后客户端应该尝试连接。服务器和客户端是两个不同的控制台应用程序。

现在,为了测试程序,我将与客户端相关的代码移动到一个测试项目中,并从它的正常项目中运行服务器。这是可行的,测试通过了:

代码语言:javascript
复制
 [TestClass]
 public class UnitTest1
 {
    static TcpClient connectionSocket = new TcpClient("localhost", 5678);
    static Stream ns = connectionSocket.GetStream();
    static StreamReader sr = new StreamReader(ns);
    static StreamWriter sw = new StreamWriter(ns);
    [TestMethod]
    public void TestMethodAdd()
    {
        int response = GetResponce("Add 5 5");
        Assert.AreEqual(response, 10);
    }

    [TestMethod]
    public void TestMethodSubstract()
    {
        int response = GetResponce("Substract 5 5");
        Assert.AreEqual(response, 0);
    }

    [TestMethod]
    public void TestMethodMultiply()
    {
        int response = GetResponce("Multiply 5 5");
        Assert.AreEqual(response, 25);
    }

    [TestMethod]
    public void TestMethodDivide()
    {
        int response = GetResponce("Divide 5 5");
        Assert.AreEqual(response, 1);
    }

    [TestMethod]
    public void TestMethodPercent()
    {
        int response = GetResponce("Percent 100 5");
        Assert.AreEqual(response, 5);
        KillConnection();
    }

    private static void KillConnection()
    {
        connectionSocket.Close();
        ns.Close();
    }

    private static int GetResponce(string request)
    {
        sw.AutoFlush = true;
        sw.WriteLine(request);
        string message = sr.ReadLine();
        return Convert.ToInt32(message);
    }
}

我应该执行的下一步是使单元测试自给自足,将其编码为通过ClassInitialize自己创建、启动和停止服务器。

我该怎么做?

这不工作,我的尝试是移动测试类中的服务器代码,然后运行使用ClassInitialize启动它的方法。

代码语言:javascript
复制
        class TcpChatServerA
{
    public void StartServer()
    {
        TcpListener listener = new TcpListener(5678);
        //Console.WriteLine("Server is started.");
        listener.Start();
        TcpClient connectionSocket = listener.AcceptTcpClient();
        ChatService service = new ChatService(connectionSocket);
        service.ServiceHandler();
        listener.Stop();
    }
}

class ChatService
{
    private TcpClient connectionSocket;
    public ChatService(TcpClient connectonSocketEntry)
    {
        connectionSocket = connectonSocketEntry;
    }
    public void ServiceHandler()
    {

        //Console.WriteLine("Server is activated");
        Stream ns = connectionSocket.GetStream();
        StreamReader sr = new StreamReader(ns);
        StreamWriter sw = new StreamWriter(ns);
        sw.AutoFlush = true;
        string message = sr.ReadLine();
        char[] deliminerChars = { ' ', ',', '.', '/', ':', ';' };
        string[] equationMembers = new string[5];
        int result = 0;
        while (message != null)
        {
            equationMembers = message.Split(deliminerChars);
            switch (equationMembers[0])
            {
                case "Add":
                    message = Convert.ToString(Convert.ToInt32(equationMembers[1]) + Convert.ToInt32(equationMembers[2]));
                    break;
                case "Substract":
                    message = Convert.ToString(Convert.ToInt32(equationMembers[1]) - Convert.ToInt32(equationMembers[2]));
                    break;
                case "Multiply":
                    message = Convert.ToString(Convert.ToInt32(equationMembers[1]) * Convert.ToInt32(equationMembers[2]));
                    break;
                case "Divide":
                    if (equationMembers[1] == "0")
                    {
                        message = "You attempt to divide by zero please try again";
                    }
                    else if (equationMembers[2] == "0")
                    {
                        message = "You attempt to divide by zero please try again";
                    }
                    else
                    {
                        message = Convert.ToString(Convert.ToDecimal(equationMembers[1]) / Convert.ToDecimal(equationMembers[2]));
                        ;
                    }
                    break;
                case "Percent":
                    message = Convert.ToString(((Convert.ToDecimal(equationMembers[2])) / 100) * Convert.ToDecimal(equationMembers[1]));
                    break;
                default:
                    Console.WriteLine("You did not enter a valid equation command. Valid commands are " +
                                      "'Add', 'Substract', 'Multiply', 'Divide', Percent (y% (from) x)");
                    break;
            }
            //Console.WriteLine("Calculating...");
            sw.WriteLine(message);
            message = sr.ReadLine();
        }
        ns.Close();
        connectionSocket.Close();
    }
}

并启动服务器:

代码语言:javascript
复制
[TestClass]
public class UnitTest1
{
    [ClassInitialize]
    static void Main(string[] args)
    {
        TcpChatServerA server = new TcpChatServerA();
        server.StartServer();
    }

    //the rest is the test class as seen in the first code block

    //static TcpClient connectionSocket = new TcpClient("localhost", 5678);
    //static Stream ns = connectionSocket.GetStream();
    //static StreamReader sr = new StreamReader(ns);
    //static StreamWriter sw = new StreamWriter(ns);

    //[TestMethod]
    //public void TestMethodAdd()
    //{
        //int response = GetResponce("Add 5 5");
        //Assert.AreEqual(response, 10);
    //}
    //...

因此,整个守则将是:

代码语言:javascript
复制
using System;
using System.IO;
using System.Net.Sockets;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MathTCPServerTest
{
class TcpChatServerA
{
    public void StartServer()
    {
        TcpListener listener = new TcpListener(5678);
        //Console.WriteLine("Server is started.");
        listener.Start();
        TcpClient connectionSocket = listener.AcceptTcpClient();
        ChatService service = new ChatService(connectionSocket);
        service.ServiceHandler();
        listener.Stop();
    }
}

class ChatService
{
    private TcpClient connectionSocket;
    public ChatService(TcpClient connectonSocketEntry)
    {
        connectionSocket = connectonSocketEntry;
    }
    public void ServiceHandler()
    {

        //Console.WriteLine("Server is activated");
        Stream ns = connectionSocket.GetStream();
        StreamReader sr = new StreamReader(ns);
        StreamWriter sw = new StreamWriter(ns);
        sw.AutoFlush = true;
        string message = sr.ReadLine();
        char[] deliminerChars = { ' ', ',', '.', '/', ':', ';' };
        string[] equationMembers = new string[5];
        int result = 0;
        while (message != null)
        {
            equationMembers = message.Split(deliminerChars);
            switch (equationMembers[0])
            {
                case "Add":
                    message = Convert.ToString(Convert.ToInt32(equationMembers[1]) + Convert.ToInt32(equationMembers[2]));
                    break;
                case "Substract":
                    message = Convert.ToString(Convert.ToInt32(equationMembers[1]) - Convert.ToInt32(equationMembers[2]));
                    break;
                case "Multiply":
                    message = Convert.ToString(Convert.ToInt32(equationMembers[1]) * Convert.ToInt32(equationMembers[2]));
                    break;
                case "Divide":
                    if (equationMembers[1] == "0")
                    {
                        message = "You attempt to divide by zero please try again";
                    }
                    else if (equationMembers[2] == "0")
                    {
                        message = "You attempt to divide by zero please try again";
                    }
                    else
                    {
                        message = Convert.ToString(Convert.ToDecimal(equationMembers[1]) / Convert.ToDecimal(equationMembers[2]));
                        ;
                    }
                    break;
                case "Percent":
                    message = Convert.ToString(((Convert.ToDecimal(equationMembers[2])) / 100) * Convert.ToDecimal(equationMembers[1]));
                    break;
                default:
                    Console.WriteLine("You did not enter a valid equation command. Valid commands are " +
                                      "'Add', 'Substract', 'Multiply', 'Divide', Percent (y% (from) x)");
                    break;
            }
            //Console.WriteLine("Calculating...");
            sw.WriteLine(message);
            message = sr.ReadLine();
        }
        ns.Close();
        connectionSocket.Close();
    }
}

[TestClass]
public class UnitTest1
{
    [ClassInitialize]
    static void Main(string[] args)
    {
        TcpChatServerA server = new TcpChatServerA();
        server.StartServer();
    }

    static TcpClient connectionSocket = new TcpClient("localhost", 5678);
    static Stream ns = connectionSocket.GetStream();
    static StreamReader sr = new StreamReader(ns);
    static StreamWriter sw = new StreamWriter(ns);

    [TestMethod]
    public void TestMethodAdd()
    {
        int response = GetResponce("Add 5 5");
        Assert.AreEqual(response, 10);
    }

    [TestMethod]
    public void TestMethodSubstract()
    {
        int response = GetResponce("Substract 5 5");
        Assert.AreEqual(response, 0);
    }

    [TestMethod]
    public void TestMethodMultiply()
    {
        int response = GetResponce("Multiply 5 5");
        Assert.AreEqual(response, 25);
    }

    [TestMethod]
    public void TestMethodDivide()
    {
        int response = GetResponce("Divide 5 5");
        Assert.AreEqual(response, 1);
    }

    [TestMethod]
    public void TestMethodPercent()
    {
        int response = GetResponce("Percent 100 5");
        Assert.AreEqual(response, 5);
        KillConnection();
    }

    private static void KillConnection()
    {
        connectionSocket.Close();
        ns.Close();
    }

    private static int GetResponce(string request)
    {
        sw.AutoFlush = true;
        sw.WriteLine(request);
        string message = sr.ReadLine();
        return Convert.ToInt32(message);
    }
}
}

这给我带来了以下错误:

测试名称: TestMethodPercent

测试FullName: MathTCPServerTest.UnitTest1.TestMethodPerent

测试源:我的目录\MathTCPServerTest\UnitTest1.cs:第132行

测试结果:失败

测试持续时间: 0:00:00

结果StackTrace:

在System.Net.Sockets.TcpClient..ctor(字符串主机名,Int32端口)

代码语言:javascript
复制
at MathTCPServerTest.UnitTest1..cctor() in _My Directories_\MathTCPServerTest\UnitTest1.cs:line 97

-内部异常堆栈跟踪结束

代码语言:javascript
复制
 at MathTCPServerTest.UnitTest1..ctor() Result Message: Unable to create instance of class MathTCPServerTest.UnitTest1. Error: System.TypeInitializationException: The type initializer for 'MathTCPServerTest.UnitTest1' threw an exception. --->   System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:5678.

我没有正确理解ClassInitialize,是吗?

PS:对于代码改进以及如何更好地在堆栈溢出中提出问题和问题,我都愿意听取建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-04 22:05:25

如何为每个单元测试创建、启动和处理TCP服务器

我应该执行的下一步是使单元测试自给自足,将其编码为通过ClassInitialize自己创建、启动和停止服务器。 我该怎么做?

由于您希望开始和停止每个单元测试,并且在一个[TestClass]中包含其中的几个,所以[ClassInitialize]在这里没有用处。一种方法是将您的测试环境封装在实现IDisposable的类中,然后在单元测试中的using块中使用它。下面的代码会这样做,并回答了如何为每个单元测试创建、启动和释放TCP服务器的问题。

代码语言:javascript
复制
using System;
using System.Net.Sockets;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;

namespace TCPServerTest
{
    class TestEnvironment : IDisposable
    {
        TcpListener TcpServer;

        readonly public int TcpServerAddress;

        public TestEnvironment(int TcpServerAddress = 5678)
        {
            this.TcpServerAddress = TcpServerAddress;

            TcpServer = new TcpListener(IPAddress.Loopback, TcpServerAddress);

            TcpServer.Start();
        }

        public void Dispose()
        {
            TcpServer.Stop();
        }
    }

    [TestClass]
    public class TestContainer
    {
        [TestMethod]
        public void TestUsingTcpServer()
        {
            using (var TestEnvironment = new TestEnvironment())
            {
                var TcpClient = new TcpClient();

                TcpClient.Connect(IPAddress.Loopback, TestEnvironment.TcpServerAddress);

                Assert.IsTrue(TcpClient.Connected, "TcpClient.Connected");
            }
        }
    }
}

论ClassInitialize

我没有正确理解ClassInitialize,是吗?

考虑到你发布的代码,这似乎是可能的。这就是框架对带有[ClassInitialize]属性的方法的说明:

该方法必须是静态的、公共的,不返回值,并且应该接受TestContext类型的单个参数。

但是,即使您使用了[ClassInitialize]所需的签名,您仍然会得到相同的异常,因为您的静态字段初始化器(异常产生的地方)是在前面执行的。

票数 0
EN

Stack Overflow用户

发布于 2016-01-04 19:57:26

我认为您已经很好地理解了ClassInitialize,但是问题是您得到了一个Type初始化异常,这个异常通常是在类的静态字段无法初始化时抛出的。我不认为您可以使TcpClient和static -它们应该在方法的某个地方被初始化。我建议删除UnitTest1类中的所有静态字段,然后将它们移到GetResponse方法中,如下所示:

代码语言:javascript
复制
private static int GetResponce(string request)
{
    TcpClient connectionSocket = new TcpClient("localhost", 5678);
    Stream ns = connectionSocket.GetStream();
    StreamReader sr = new StreamReader(ns);
    StreamWriter sw = new StreamWriter(ns);

    sw.AutoFlush = true;
    sw.WriteLine(request);
    string message = sr.ReadLine();
    return Convert.ToInt32(message);
}

(这个应该很好地工作:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34597920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档