4

以下のように、FTP サーバーからファイルのリストを取得する方法があります。

    public List<string> FetchFilesList()
    {
        var request = WebRequest.Create(FtpServerUri);
        request.Method = WebRequestMethods.Ftp.ListDirectory;

        request.Credentials = Credentials;

        using (var response = request.GetResponse())
        {
            var responseStream = response.GetResponseStream();

            using (var reader = new StreamReader(responseStream))
            {
                var fileNamesString = reader.ReadToEnd();
                var fileNames = fileNamesString.Split(
                    Environment.NewLine.ToCharArray(), 
                    StringSplitOptions.RemoveEmptyEntries);

                return fileNames.ToList();
            }
        }
    }

FTP の代わりにローカル ディレクトリにアクセスする UT を作成しようとしています。

ここに私のUTがあります:

// ftpFetcherTestWrapper is thin wrapper to expose properties to UT
// TODO: For some reason providing credentials like this doesn't work :(
// It also doesn't work for DefaultNetworkCredentials
ftpFetcherTestWrapper.CredentialsExposed = CredentialCache.DefaultCredentials;
// As we are using wrapper we substitude FtpServerUri to our fake-local folder
ftpFetcherTestWrapper.ServerUriExposed = new Uri(directoryName);

var filesList = ftpSFetcherTestWrapper.FetchFilesList();

私は受け取りますSystem.Net.WebException: "Access to the path 'D:\\SomePathToUnitTestsExecutionFolder\\XmlFiles' is denied."

Q:単体テストでリモート FTP の代わりに WebRequest がローカル フォルダーにアクセスするために使用する Windows/ネットワーク資格情報を渡すことは可能ですか?

[編集]

ftp パスの代わりにローカル ファイル パスを指定すると、ファイル コンテンツのフェッチをテストできることに注意してください。

public XDocument FetchFile(string fileName)
{
    var client = new WebClient();
    client.Credentials = Credentials;

    var fileUri = new Uri(FtpServerUri, fileName);
    var downloadedXml = client.DownloadString(fileUri);
    return XDocument.Parse(downloadedXml);
}

また、私が行っていることが単体テストの 100% フィートの定義ではないことも承知していますが、それでもこれは良いテストだと思います。

4

3 に答える 3

2

fetchFilesList()を(Webrequestへの)依存関係でテストすることを統合テストと呼びます。ユニットテスト、つまり、fetchFilesList()が具体的に実行しているテストを作成したいと思います。単体テストでWebRequestをテストする必要はありません。あなたはそれがすべきことをしていると断言するべきです。これを実現するには、カプセル化してモックする必要があります。WebRequestを構成して返すFtpWebRequestFactoryを個人的に作成します。

private FtpWebRequestFactory ftpWebRequestFactory;

public FtpFetcher(FtpWebRequestFactory ftpWebRequestFactory) {
    this.ftpWebRequestFactory = ftpWebRequestFactory;
}

public List<string> FetchFilesList()
{
    var request = ftpWebRequestFactory.Create(FtpServerUri);

    using (var response = request.GetResponse())
    {
        var responseStream = response.GetResponseStream();

        using (var reader = new StreamReader(responseStream))
        {
            var fileNamesString = reader.ReadToEnd();
            var fileNames = fileNamesString.Split(
                    Environment.NewLine.ToCharArray(),
                    StringSplitOptions.RemoveEmptyEntries);

            return fileNames.ToList();
        }
    }
}

単体テストでは、モックフレームワーク(moqなど)を使用して、FtpWebRequestFactoryのモックを作成します。モックリクエストを返すようにモックを設定し、モックレスポンスを返すようにこのモックリクエストを設定します。この時点で、正しいストリームを返すように応答を簡単に構成できます。

于 2012-04-15T17:06:49.420 に答える
1

そのフォルダを共有してから、ネットワーク パスとしてアクセスするのはどうですか? つまり、\\my-pc-name\the-folder?

少しグーグルで検索: http://www.velocityreviews.com/forums/t78357-webrequest-and-shared-files.html

WebRequest request = WebRequest.Create("http://localhost/tempasp/temp/trace.txt" );
request.PreAuthenticate = true;
request.Credentials = new NetworkCredential("user", "pass", "domain" );

WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader( response.GetResponseStream() );

string line = String.Empty;
while ( ( line = reader.ReadLine() ) != null )
{
    Response.Write( line );
    Response.Write( "<BR>" );
}
reader.Close();
response.Close();

これでうまくいきますか?

于 2012-04-12T13:23:09.837 に答える
1

おそらく、要求の Uri にアドレススキーム(つまり、「ファイル」) を追加する必要があります。そうしないと、.NET はリソースへのアクセスに使用するプロトコルを認識できません。また、ローカル ファイルにアクセスしているため、ほとんどの場合、既に承認されているため、資格情報を設定する必要はありません。次のコードを試してください。

    static void Main(string[] args)
    {
        Uri uri = new Uri(@"file:///C:\BuddyBuild\x.xml");
        FetchFilesList(uri);
        Console.ReadLine();
    }

    static List<string> FetchFilesList(Uri uri)
    {
        var request = WebRequest.Create(uri);
        request.Method = WebRequestMethods.Ftp.ListDirectory;
        //request.Credentials = CredentialCache.DefaultCredentials;

        using (var response = request.GetResponse())
        {
            var responseStream = response.GetResponseStream();
            using (var reader = new StreamReader(responseStream))
            {
                var fileNamesString = reader.ReadToEnd();
                var fileNames = fileNamesString.Split(
                    Environment.NewLine.ToCharArray(),
                    StringSplitOptions.RemoveEmptyEntries);

                return fileNames.ToList();
            }
        }
    }

Mainの最初の行「file:///path_to_your_file」に注意してください。

ただし、Pierre-Henriが指摘したように、これはUnit Testには適していないように見えます。あなたがテストしようとしている「ユニット」はどれですか?FtpWebRequest部分ですか、それともファイル コンテンツをリストに分割した部分ですか? 代わりに、FetchFilesList メソッドを 2 つに分割します。

    public static List<String> FetchList(Stream stream)
    {
        using (var reader = new StreamReader(stream))
        {
            var fileNamesString = reader.ReadToEnd();
            var fileNames = fileNamesString.Split(
                Environment.NewLine.ToCharArray(),
                StringSplitOptions.RemoveEmptyEntries);

            return fileNames.ToList();
        }
    }

    public static List<string> FetchFilesList2(Uri uri)
    {
        var request = WebRequest.Create(uri);
        request.Method = WebRequestMethods.Ftp.ListDirectory;

        using (var response = request.GetResponse())
        {
            return FetchList(response.GetResponseStream());
        }
    }

このようにして、2 つのメソッドの単体テストを個別に実行できます。特に、任意のStreamオブジェクト (FileStream、MemoryStream、WebResponse の Stream など) でFetchList(Stream stream)をテストできます。

EDIT : 申し訳ありませんが、URI をローカル ディレクトリに設定して、(ローカル) ディレクトリ内のファイルを一覧表示しようとしていることに気付きませんでした。WebRequest/Response クラス ファミリでそれを行うことはできないと思います。URI パラメーターをローカル パスに設定すると、WebRequest.Create 呼び出しはFileWebRequestオブジェクトを返します。このオブジェクトは、内部的にFileWebStreamを使用してローカル ファイルにアクセスします。FileWebStream はFileStreamを継承します、ディレクトリには使用できません。ところで、URI パラメータを FTP アドレスに設定すると、WebRequest.Create 呼び出しは代わりに FtpWebRequest オブジェクトを返します。これは、これが良い単体テストではないと思う理由の 1 つでもあります :)。おそらく、FileWebRequest (FtpWebRequest は封印されています) を拡張して、ディレクトリ リストの要求を処理することができます。

于 2012-04-18T15:17:50.467 に答える