Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 596433
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T16:10:17+00:00 2026-05-13T16:10:17+00:00

I don’t have much experience doing unit testing. From what I learned, code should

  • 0

I don’t have much experience doing unit testing. From what I learned, code should be decoupled, and I should not strive to test private code, just public methods, setters, etc etc.

Now, I have grasped some basic testing concepts, but I have troubles applying more advanced stuff to this case… Dependency Injection, Inversion of Control, Mock Objects, etc – can’t get my head around it just yet 🙁

Before I move on to code, here are the questions.

  • In a given class, what exactly should I try to test?
  • How can I accomplish those test tasks?
  • Is there something seriously wrong with class design, which prevents testing from being done properly (or is something just plain wrong even outside of testing context)?
  • What design patterns are useful to testing network code in general?

Also, I’ve been trying to obey “write tests first, then write code to make tests pass”, that’s why I wrote first two tests that simply instantiate class and run it, but then, when server was able to start and accept packets, I didn’t know what to test next…

Okay, here goes the code snippet. (note: original code is split in several namespaces, that’s why it may appear a little out of order)

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace MyProject1
{
    /// <summary>
    /// Packet buffer that is sent to/received from connection
    /// </summary>
    public class UDPPacketBuffer
    {
        /// <summary>
        /// Buffer size constant
        /// </summary>
        public const int BUFFER_SIZE = 4096;

        private byte[] _data;

        /// <summary>
        /// Byte array with buffered data
        /// 
        /// DataLength is automatically updated when Data is set
        /// </summary>
        /// <see cref="DataLength"/>
        public byte[] Data { get { return _data; } set { _data = value; DataLength = value.Length; } }

        /// <summary>
        /// Integer with length of buffered data
        /// </summary>
        public int DataLength;

        /// <summary>
        /// Remote end point (IP Address and Port)
        /// </summary>
        public EndPoint RemoteEndPoint;

        /// <summary>
        /// Initializes <see cref="UDPPacketBuffer"/> class
        /// </summary>
        public UDPPacketBuffer()
        {
            // initialize byte array
            this.Data = new byte[BUFFER_SIZE];

            // this will be filled in by the caller (eg. udpSocket.BeginReceiveFrom)
            RemoteEndPoint = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
        }

        /// <summary>
        /// Returns <see cref="Data"/> as a byte array shortened to <see cref="DataLength"/> number of bytes
        /// </summary>
        public byte[] ByteContent
        {
            get
            {
                if (DataLength > 0)
                {
                    byte[] content = new byte[DataLength];
                    for (int i = 0; i < DataLength; i++)
                        content[i] = Data[i];
                    return content;
                }
                else
                {
                    return Data;
                }
            }
        }

        /// <summary>
        /// Returns <see cref="ByteContent"/> converted to string
        /// </summary>
        public string StringContent { get { return Encoding.ASCII.GetString(ByteContent); } }
    }

    /// <summary>
    /// UDP packet-related event arguments passed when invoking events
    /// </summary>
    /// <example>
    /// This example shows how to use UDPPacketEventArgs class when event is invoked.
    /// <code>
    /// if (PacketSent != null)
    ///     PacketSent(this, new UDPPacketEventArgs(buffer, bytesSent));
    /// </code>
    /// </example>
    public class UDPPacketEventArgs : EventArgs
    {
        /// <summary>
        /// Instance of UDPPacketBuffer, holding current event-related buffer
        /// </summary>
        public UDPPacketBuffer buffer { get; private set; }

        /// <summary>
        /// Number of bytes sent to remote end point
        /// </summary>
        public int sent { get; private set; }

        /// <summary>
        /// Initializes <see cref="buffer"/> only. Used when receiving data.
        /// </summary>
        /// <param name="buffer">Buffer sent to or received from remote endpoint</param>
        public UDPPacketEventArgs(UDPPacketBuffer buffer)
        {
            this.buffer = buffer;
        }

        /// <summary>
        /// Initializes <see cref="buffer"/> and <see cref="sent"/> variables. Used when sending data.
        /// </summary>
        /// <param name="buffer">buffer that has been sent</param>
        /// <param name="sent">number of bytes sent</param>
        public UDPPacketEventArgs(UDPPacketBuffer buffer, int sent)
        {
            this.buffer = buffer;
            this.sent = sent;
        }
    }

    /// <summary>
    /// Asynchronous UDP server
    /// </summary>
    public class AsyncUdp : ServerBase
    {
        private const int _defaultPort = 45112;

        private int _udpPort;

        /// <summary>
        /// Port number on which server should listen
        /// </summary>
        public int udpPort { get { return _udpPort; } private set { _udpPort = value; } }

        // should server listen for broadcasts?
        private bool broadcast = false;

        // server socket
        private Socket udpSocket;

        // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()).
        // since there are potentially many "reader" threads in the internal .NET IOCP
        // thread pool, this is a cheaper synchronization primitive than using
        // a Mutex object.  This allows many UDP socket "reads" concurrently - when
        // Stop() is called, it attempts to obtain a writer lock which will then
        // wait until all outstanding operations are completed before shutting down.
        // this avoids the problem of closing the socket with outstanding operations
        // and trying to catch the inevitable ObjectDisposedException.
        private ReaderWriterLock rwLock = new ReaderWriterLock();

        // number of outstanding operations.  This is a reference count
        // which we use to ensure that the threads exit cleanly. Note that
        // we need this because the threads will potentially still need to process
        // data even after the socket is closed.
        private int rwOperationCount = 0;

        // the all important shutdownFlag.  This is synchronized through the ReaderWriterLock.
        private bool shutdownFlag = true;

        /// <summary>
        /// Returns server running state
        /// </summary>
        public bool IsRunning
        {
            get { return !shutdownFlag; }
        }

        /// <summary>
        /// Initializes UDP server with arbitrary default port
        /// </summary>
        public AsyncUdp()
        {
            this.udpPort = _defaultPort;
        }

        /// <summary>
        /// Initializes UDP server with specified port number
        /// </summary>
        /// <param name="port">Port number for server to listen on</param>
        public AsyncUdp(int port)
        {
            this.udpPort = port;
        }

        /// <summary>
        /// Initializes UDP server with specified port number and broadcast capability
        /// </summary>
        /// <param name="port">Port number for server to listen on</param>
        /// <param name="broadcast">Server will have broadcasting enabled if set to true</param>
        public AsyncUdp(int port, bool broadcast)
        {
            this.udpPort = port;
            this.broadcast = broadcast;
        }

        /// <summary>
        /// Raised when packet is received via UDP socket
        /// </summary>
        public event EventHandler PacketReceived;

        /// <summary>
        /// Raised when packet is sent via UDP socket
        /// </summary>
        public event EventHandler PacketSent;

        /// <summary>
        /// Starts UDP server
        /// </summary>
        public override void Start()
        {
            if (! IsRunning)
            {
                // create and bind the socket
                IPEndPoint ipep = new IPEndPoint(IPAddress.Any, udpPort);
                udpSocket = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Dgram,
                    ProtocolType.Udp);
                udpSocket.EnableBroadcast = broadcast;
                // we don't want to receive our own broadcasts, if broadcasting is enabled
                if (broadcast)
                    udpSocket.MulticastLoopback = false;
                udpSocket.Bind(ipep);

                // we're not shutting down, we're starting up
                shutdownFlag = false;

                // kick off an async receive.  The Start() method will return, the
                // actual receives will occur asynchronously and will be caught in
                // AsyncEndRecieve().
                // I experimented with posting multiple AsyncBeginReceives() here in an attempt
                // to "queue up" reads, however I found that it negatively impacted performance.
                AsyncBeginReceive();
            }
        }

        /// <summary>
        /// Stops UDP server, if it is running
        /// </summary>
        public override void Stop()
        {
            if (IsRunning)
            {
                // wait indefinitely for a writer lock.  Once this is called, the .NET runtime
                // will deny any more reader locks, in effect blocking all other send/receive
                // threads.  Once we have the lock, we set shutdownFlag to inform the other
                // threads that the socket is closed.
                rwLock.AcquireWriterLock(-1);
                shutdownFlag = true;
                udpSocket.Close();
                rwLock.ReleaseWriterLock();

                // wait for any pending operations to complete on other
                // threads before exiting.
                while (rwOperationCount > 0)
                    Thread.Sleep(1);
            }
        }

        /// <summary>
        /// Dispose handler for UDP server. Stops the server first if it is still running
        /// </summary>
        public override void Dispose()
        {
            if (IsRunning == true)
                this.Stop();
        }

        private void AsyncBeginReceive()
        {
            // this method actually kicks off the async read on the socket.
            // we aquire a reader lock here to ensure that no other thread
            // is trying to set shutdownFlag and close the socket.
            rwLock.AcquireReaderLock(-1);

            if (!shutdownFlag)
            {
                // increment the count of pending operations
                Interlocked.Increment(ref rwOperationCount);

                // allocate a packet buffer
                UDPPacketBuffer buf = new UDPPacketBuffer();

                try
                {
                    // kick off an async read
                    udpSocket.BeginReceiveFrom(
                        buf.Data,
                        0,
                        UDPPacketBuffer.BUFFER_SIZE,
                        SocketFlags.None,
                        ref buf.RemoteEndPoint,
                        new AsyncCallback(AsyncEndReceive),
                        buf);
                }
                catch (SocketException)
                {
                    // an error occurred, therefore the operation is void.  Decrement the reference count.
                    Interlocked.Decrement(ref rwOperationCount);
                }
            }

            // we're done with the socket for now, release the reader lock.
            rwLock.ReleaseReaderLock();
        }

        private void AsyncEndReceive(IAsyncResult iar)
        {
            // Asynchronous receive operations will complete here through the call
            // to AsyncBeginReceive

            // aquire a reader lock
            rwLock.AcquireReaderLock(-1);

            if (!shutdownFlag)
            {
                // start another receive - this keeps the server going!
                AsyncBeginReceive();

                // get the buffer that was created in AsyncBeginReceive
                // this is the received data
                UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;

                try
                {
                    // get the length of data actually read from the socket, store it with the
                    // buffer
                    buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);

                    // this operation is now complete, decrement the reference count
                    Interlocked.Decrement(ref rwOperationCount);

                    // we're done with the socket, release the reader lock
                    rwLock.ReleaseReaderLock();

                    // run event PacketReceived(), passing the buffer that
                    // has just been filled from the socket read.
                    if (PacketReceived != null)
                        PacketReceived(this, new UDPPacketEventArgs(buffer));
                }
                catch (SocketException)
                {
                    // an error occurred, therefore the operation is void.  Decrement the reference count.
                    Interlocked.Decrement(ref rwOperationCount);

                    // we're done with the socket for now, release the reader lock.
                    rwLock.ReleaseReaderLock();
                }
            }
            else
            {
                // nothing bad happened, but we are done with the operation
                // decrement the reference count and release the reader lock
                Interlocked.Decrement(ref rwOperationCount);
                rwLock.ReleaseReaderLock();
            }
        }

        /// <summary>
        /// Send packet to remote end point speified in <see cref="UDPPacketBuffer"/>
        /// </summary>
        /// <param name="buf">Packet to send</param>
        public void AsyncBeginSend(UDPPacketBuffer buf)
        {
            // by now you should you get the idea - no further explanation necessary

            rwLock.AcquireReaderLock(-1);

            if (!shutdownFlag)
            {
                try
                {
                    Interlocked.Increment(ref rwOperationCount);
                    udpSocket.BeginSendTo(
                        buf.Data,
                        0,
                        buf.DataLength,
                        SocketFlags.None,
                        buf.RemoteEndPoint,
                        new AsyncCallback(AsyncEndSend),
                        buf);
                }
                catch (SocketException)
                {
                    throw new NotImplementedException();
                }
            }

            rwLock.ReleaseReaderLock();
        }

        private void AsyncEndSend(IAsyncResult iar)
        {
            // by now you should you get the idea - no further explanation necessary

            rwLock.AcquireReaderLock(-1);

            if (!shutdownFlag)
            {
                UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;

                try
                {
                    int bytesSent = udpSocket.EndSendTo(iar);

                    // note that in invocation of PacketSent event - we are passing the number
                    // of bytes sent in a separate parameter, since we can't use buffer.DataLength which
                    // is the number of bytes to send (or bytes received depending upon whether this
                    // buffer was part of a send or a receive).
                    if (PacketSent != null)
                        PacketSent(this, new UDPPacketEventArgs(buffer, bytesSent));
                }
                catch (SocketException)
                {
                    throw new NotImplementedException();
                }
            }

            Interlocked.Decrement(ref rwOperationCount);
            rwLock.ReleaseReaderLock();
        }
    }

    /// <summary>
    /// Base class used for all network-oriented servers.
    /// <para>Disposable. All methods are abstract, including Dispose().</para>
    /// </summary>
    /// <example>
    /// This example shows how to inherit from ServerBase class.
    /// <code>
    /// public class SyncTcp : ServerBase {...}
    /// </code>
    /// </example>
    abstract public class ServerBase : IDisposable
    {
        /// <summary>
        /// Starts the server.
        /// </summary>
        abstract public void Start();

        /// <summary>
        /// Stops the server.
        /// </summary>
        abstract public void Stop();

        #region IDisposable Members

        /// <summary>
        /// Cleans up after server.
        /// <para>It usually calls Stop() if server is running.</para>
        /// </summary>
        public abstract void Dispose();

        #endregion
    }
}

“Test code” follows.

namespace MyProject1
{
    class AsyncUdpTest
    {
        [Fact]
        public void UdpServerInstance()
        {
            AsyncUdp udp = new AsyncUdp();
            Assert.True(udp is AsyncUdp);
            udp.Dispose();
        }

        [Fact]
        public void StartStopUdpServer()
        {
            using (AsyncUdp udp = new AsyncUdp(5000))
            {
                udp.Start();
                Thread.Sleep(5000);
            }
        }


        string udpReceiveMessageSend = "This is a test message";
        byte[] udpReceiveData = new byte[4096];
        bool udpReceivePacketMatches = false;

        [Fact]
        public void UdpServerReceive()
        {

            using (AsyncUdp udp = new AsyncUdp(5000))
            {
                udp.Start();
                udp.PacketReceived += new EventHandler(delegate(object sender, EventArgs e)
                {
                    UDPPacketEventArgs ea = e as UDPPacketEventArgs;
                    if (this.udpReceiveMessageSend.Equals(ea.buffer.StringContent))
                    {
                        udpReceivePacketMatches = true;
                    }
                });
                // wait 20 ms for a socket to be bound etc
                Thread.Sleep(20);

                UdpClient sock = new UdpClient();
                IPEndPoint iep = new IPEndPoint(IPAddress.Loopback, 5000);

                this.udpReceiveData = Encoding.ASCII.GetBytes(this.udpReceiveMessageSend);
                sock.Send(this.udpReceiveData, this.udpReceiveData.Length, iep);
                sock.Close();

                // wait 20 ms for an event to fire, it should be enough
                Thread.Sleep(20);

                Assert.True(udpReceivePacketMatches);
            }
        }
    }
}

note: code is c#, testing framework xUnit

A big thanks to everyone who takes time to go through my question and answer it!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T16:10:17+00:00Added an answer on May 13, 2026 at 4:10 pm

    Should you test ? Absolutely. You need to engineer your code for testability to make this simple. Your first statement is largely correct. So, some further comments:

    Unit testing is largely testing code alone against test data and not reliant on external systems/servers etc. Functional/integration testing then brings in your external servers/databases etc. You can use dependency injection to inject either that real external system reference, or a test (mocked) system implementing the same interface, and thus your code becomes easily testable.

    So in the above you would probably want to inject the UDP data source into your receiver. Your data source would implement a particular interface, and a mocked (or simple test) source would provide different packets for testing (e.g. empty, containing valid data, containing invalid data). That would form the basis of your unit test.

    Your integration (or functional? I never know what to call it) test would perhaps start up a test UDP data source in the same VM, for each test, and pump data via UDP to your receiver. So now you’ve tested the basic functionality in the face of different packets via your unit test, and you’re testing the actual UDP client/server function via your integration test.

    So now you’ve tested your packet transmission/reception, you can test further parts of your code. Your UDP receiver will plug into another component, and here you can use dependency injection to inject the UDP receiver into your upstream component, or a mocked/test receiver implementing the same interface (and so on).

    (Note: given that UDP transmission is unreliable even intra-host you should be prepared to cater for that somehow, or accept that infrequently you’ll have problems. But that’s a UDP-specific issue).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 435k
  • Answers 435k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer You can call the Measure() method in order to ask… May 15, 2026 at 3:32 pm
  • Editorial Team
    Editorial Team added an answer The name of you named query is really its name,… May 15, 2026 at 3:32 pm
  • Editorial Team
    Editorial Team added an answer There's no such function, at least none I know of.… May 15, 2026 at 3:32 pm

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.