DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Integration Testing FTP Connections in .NET

Integration Testing FTP Connections in .NET

Douglas Rathbone user avatar by
Douglas Rathbone
·
Sep. 27, 12 · Interview
Like (0)
Save
Tweet
Share
5.52K Views

Join the DZone community and get the full member experience.

Join For Free

when writing testable code, your first port of call is often to abstract any dependencies and make them easy to mock. this is the same for any of your codebase that talks to ftp servers. testing the way your code behaves under real world conditions makes integration tests important regardless of abstraction, though. here’s a simple trick to test ftp code in the wild.

image a recent project of mine has involved writing code that talks to ftp servers with the goal of adding additional continuous integration automation to a project. although all of my main methods are easily abstracted and injectable, my project still needs to actually talk to ftp servers at the end of the day, and i need to test that these very methods do the right thing when they are met with different conditions; be they bad credentials, lack of read/write permissions etc.

the challenge

integration tests can be brittle at the best of times, so ensuring that they are repeatable and can be setup and torn down can often be almost as much of a challenge as writing your actual code itself.

an ftp server is usually a static service that is installed on a server. you might think that running one and ensuring it stays up and doesn’t get hacked just so that all your integration tests work is a necessary evil, but there is an easier way.

run local. run often.

i was running an ftp server on my build server just so that it was “always around” for my tests until i stumbled across an interesting project over on github to do just this .

the approach i'm about to show you doesn’t need you to go to the effort of running a dedicated server at all. all you need to do is add a single executable to your unit test project and wrap your unit test in a using statement.

the ftp server executable is a single file ftp server called ftpdmin which offers a read/write ftp server that can be fired up from the command line with a minimum feature set and only a few command line parameters to make it all tick.

by implementing idisposable the helper class that wraps around this command line exe allows you to take advantage of the using() pattern to take care of your executable’s lifetime and have it die when your code is done testing.

steps to make it happen

download ftpdmin from here .

add the exe to the root of your test project (you can put this anywhere, but you’ll have to update the helper class below).

now add the exe to your project (i.e “view all items” in your test project’s solution explorer, and add the exe).

set the exe to “copy always” in it’s solution properties.

image

add the following code to a helper class in your test project:

public class ftptestserver: idisposable
{
    private readonly process ftpprocess;

    public ftptestserver(string rootdirectory, int port = 21, bool allowuploads = true)
    {
        var psinfo = new processstartinfo
            {
                filename = appdomain.currentdomain.basedirectory + "\\ftpdmin.exe",
                arguments = string.format("-p {0} -ha 127.0.0.1 \"{1}\" {2}", port, rootdirectory, allowuploads ? string.empty : "-g"),
                windowstyle = processwindowstyle.hidden
            };
        ftpprocess = process.start(psinfo);
    }

    public void dispose()
    {
        if (ftpprocess.hasexited) return;
        ftpprocess.kill();
        ftpprocess.waitforexit();
    }
}

now you can enjoy being able to write really clean integration testing code that starts and ftp server every time you run your tests and then tear it down when your test is done.

an example integration test showing connecting to “127.0.0.1”:

[testmethod]
public void ftpcode_upload_canconnect()
{
    try
    {
        // fire up a new ftp server instance
        using (new ftptestserver(rootdirectory: "./"))
        {
            // code that talks to an ftp server on 127.0.0.1
        }
    }
    catch (webexception e)
    {
        assert.fail("failed to connect to our ftp server");
    }
}

how awesome is that?

the power of using ftpdmin is that it can be told to deny write permissions to simulate bad user permissions as well:

[testmethod]
public void ftpcode_upload_throwswebexception()
{
    try
    {
        // fire up a new ftp server instance
        using (new ftptestserver(rootdirectory: "./", allowuploads: false))
        {
            // code that talks to an ftp server on 127.0.0.1
        }
    }
    catch (webexception e)
    {
        assert.fail("our code failed to upload a file because of invalid permissions");
    }
}

all in all, the above has been a complete lifesaver when it comes to making my integration test projects portable – if a new developer joins my project, they instantly get access to my ftp test harness just by pulling down my project’s source code.

Integration unit test Integration testing File Transfer Protocol

Published at DZone with permission of Douglas Rathbone, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Continuous Development: Building the Thing Right, to Build the Right Thing
  • API Design Patterns Review
  • Building a Scalable Search Architecture
  • Microservices Discovery With Eureka

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: