2

I'm using FtpWebRequest and a Transient Fault Handling application block. For my fault handler, I have an error detection strategy that checks if the response is considered transient so that it knows whether or not to retry:

public bool IsTransient(Exception ex)
    {

        var isTransient = false;
        //will be false if the exception is not a web exception.
        var webEx = ex as WebException;

        //happens when receiving a protocol error.
        //This protocol error wraps the inner exception, e.g. a 401 access denied.
        if (webEx != null && webEx.Status == WebExceptionStatus.ProtocolError)
        {
            var response = webEx.Response as FtpWebResponse;
            if (response != null && (int)response.StatusCode < 400)
            {
                isTransient = true;
            }
        }
        // if it is a web exception but not a protocol error,
        // check the status code.
        else if (webEx != null)
        {
            //(check for transient error statuses here...)
            isTransient = true;
        }

        return isTransient;
    }

I'm trying to write some tests to check that things the appropriate errors are flagged as transient, but I'm having trouble creating or mocking a web exception that has an inner exception with an FtpWebResponse (so that the response in the following isn't always null)

var response = webEx.Response as FtpWebResponse;

Does anybody know how I can do this? Am I going about it the right way?

Chris Barlow
  • 3,274
  • 4
  • 31
  • 52
Kai
  • 147
  • 1
  • 13

2 Answers2

2

Use the appropriate constructor on WebException to set the response:

public WebException(
 string message,
 Exception innerException,
 WebExceptionStatus status,
 WebResponse response)

setting up an exception with an FtpWebResponse is the bit that I'm having trouble with... FtpWebResponse has an internal constructor that I can't access.

The BCL is not really made for testing because that concept wasn't big at the time it was written. You'll have to call that internal constructor using reflection (use a decompiler to see what's available). Or, wrap all of the System.Net classes that you need with custom mockable classes. That looks like a lot of work, though.

usr
  • 168,620
  • 35
  • 240
  • 369
  • Thanks for your response. That is the what I would like to use, but setting up an exception with an FtpWebResponse is the bit that I'm having trouble with... FtpWebResponse has an internal constructor that I can't access. – Kai Jul 18 '14 at 11:33
  • 1
    Understood. The BCL is not really made for testing because that concept wasn't big at the time it was written. You'll have to call that internal ctor using reflection (use a decompiler to see what'S available). Or, wrap all of the System.Net classes that you need with custom mockable classes. That looks like a lot of work, though. – usr Jul 18 '14 at 11:37
  • Hi @usr, could you please add the contents of your comment to your answer? I ended up not testing this because of time constraints, but I believe that your comment here is a more helpful answer. – Kai Aug 11 '14 at 09:37
0

I build my off line tests using an stub of FtpWebResponse, created by Rhino Framework

Example:

public WebException createExceptionHelper(String message, WebExceptionStatus webExceptionStatus, FtpStatusCode serverError )
{
    var ftpWebResponse = Rhino.Mocks.MockRepository.GenerateStub<FtpWebResponse>();
    ftpWebResponse.Stub(f => f.StatusCode).Return(serverError);
    ftpWebResponse.Stub(f => f.ResponseUri).Return(new Uri("http://mock.localhost"));

    //now just pass the ftpWebResponse stub object to the constructor
    return new WebException(message, null, webExceptionStatus, ftpWebResponse);
    }
MiguelSlv
  • 14,067
  • 15
  • 102
  • 169