1

単体テストのデバッグ中にブレークポイントがない場合に例外がスローされる理由がわかりませんでした。ただし、次の行にブレークポイントを設定してデバッグすると、問題なく実行されます。

これが私のコードです。

MainPageViewModel.cs

public class MainPageViewModel
{
    public async Task<IEnumerable<Event>> GetAllEvents()
    {
        WebClient client = new WebClient();
        string xmlDoc = await FXNewsAlert.Misc.Extensions.DownloadStringTask(client, new Uri("http://www.forexfactory.com/ffcal_week_this.xml")); //breakpoint here

        var events = XDocument.Parse(xmlDoc)
            .Descendants("event")
            .Select(n => new Event
            {
                Title = n.Element("title").Value,
                Country = n.Element("country").Value,
                DateTime = this.ToLocalTime(String.Format("{0} {1}", n.Element("date").Value, n.Element("time").Value)),
                Impact = n.Element("forecast").Value,
                Forecast = n.Element("forecast").Value,
                Previous = n.Element("previous").Value
            }).ToList();

        return events;
    }
}

EventsTest.cs

[TestClass]
public class EventsTest : WorkItemTest
{
    [TestMethod]
    [Asynchronous]
    public async void GetAllEventsTest()
    {
        MainPageViewModel vm = new MainPageViewModel();
        IEnumerable<Event> events = await vm.GetAllEvents(); //WebException is thrown here.

        Assert.IsTrue(events.Count() > 0);
        EnqueueTestComplete();
    }
}

私の推測では、どうにかして URL をロードするのに時間がかかるので、ブレークポイントを設定することで余分な時間を与えて、ダウンロードしている xml を時間通りに完了することができるようにします。

でも実際は非同期メソッドなので関係ないですよね?私は今かなり迷っています。どんな助けでも大歓迎です。

編集: DownloadStringTask の実装

    public static Task<string> DownloadStringTask(this WebClient webClient, Uri uri)
    {
        var tcs = new TaskCompletionSource<string>();

        webClient.DownloadStringCompleted += (s, e) =>
        {
            if (e.Error != null)
            {
                tcs.SetException(e.Error);
            }
            else
            {
                tcs.SetResult(e.Result);
            }
        };

        webClient.DownloadStringAsync(uri);

        return tcs.Task;
    }

System.Net.WebException の StackTrace

System.Net.Browser.AsyncHelper.BeginOnUI (SendOrPostCallback beginMethod、オブジェクト状態) で System.Net.Browser.ClientHttpWebRequest.EndGetResponse (IAsyncResult asyncResult) で System.Net.WebClient.GetWebResponse (WebRequest 要求、IAsyncResult 結果) で System.Net .WebClient.DownloadBitsResponseCallback(IAsyncResult result) --- 例外がスローされた前の場所からのスタック トレースの終わり --- System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) で System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(タスク task) で System.Runtime.CompilerServices.TaskAwaiter 1.GetResult() at FXNewsAlert.Resources.MainPageViewModel.<GetAllEvents>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() で FXNewsAlertTest.UnitTests.EventsTest.d__0.MoveNext()

4

2 に答える 2

1

FXNewsAlert で何か問題が発生しているように感じますが、その実装は上記に示されていません。を掘り下げる(または置き換える)ことをお勧めしFXNewsAlert.Misc.Extensions.DownloadStringTask()ます。私の推測では、ダウンロードが完了する前に降伏していると思います。

このコードをテストするために、最初に Event クラスを作成してデータを格納し、コードへの変更を最小限に抑えました。

public class Event
{
    public string Title { get; set; }
    public string Country { get; set; }
    public DateTime DateTime { get; set; }
    public string Impact { get; set; }
    public string Forecast { get; set; }
    public string Previous { get; set; }
}

次に、WebClient のDownloadStringTaskAsync()メソッドを使用するようにコードを少し変更しました。

public class MainPageViewModel
{
    public async Task<IEnumerable<Event>> GetAllEvents()
    {
        WebClient client = new WebClient();

        // HACK: Don't have access to the implementation to FXNewsAlert...
        //string xmlDoc = await FXNewsAlert.Misc.Extensions.DownloadStringTask(
        //    client, new Uri("http://www.forexfactory.com/ffcal_week_this.xml")); //breakpoint here

        string xmlDoc = await client.DownloadStringTaskAsync(
            new Uri("http://www.forexfactory.com/ffcal_week_this.xml")); //breakpoint here

        var events = XDocument.Parse(xmlDoc)
            .Descendants("event")
            .Select(n => new Event
            {
                Title = n.Element("title").Value,
                Country = n.Element("country").Value,
                DateTime = DateTime.Parse(String.Format("{0} {1}", n.Element("date").Value, n.Element("time").Value)),
                Impact = n.Element("forecast").Value,
                Forecast = n.Element("forecast").Value,
                Previous = n.Element("previous").Value
            }).ToList();

        return events;
    }
}

テスト プロジェクトを作成する代わりに、次のコンソール アプリを作成しました。

class Program
{
    static void Main(string[] args)
    {
        var vm = new MainPageViewModel();
        var task = vm.GetAllEvents();
        task.Wait();
        foreach (Event e in task.Result)
        {
            Console.WriteLine("{0} [{1}]", e.Title, e.DateTime);
            Console.WriteLine("Forecast: {0} (Previous: {1})", e.Forecast, e.Previous);
            Console.WriteLine();
        }
    }
}

このコードは、ブレークポイントの有無にかかわらず正常に実行されます。

于 2013-01-12T14:07:39.023 に答える
0

テスト方法をからasync voidに変更しますasync Task

これはクリアされませんWebExceptionが、デバッグできるように一貫性を保つ必要があります。

于 2013-01-13T04:24:51.197 に答える