سؤال

إليك واحدة للخيوط المدمرة هناك. لدي هذه الطريقة:

    public void RefreshMelts()
    {
        MeltsAvailable.Clear();

        ThreadPool.QueueUserWorkItem(delegate
        {
            Dispatcher.BeginInvoke((ThreadStart)delegate
            {
                eventAggregator.GetEvent<BusyEvent>().Publish(true);
                eventAggregator.GetEvent<StatusMessageEvent>().Publish(
                    new StatusMessage("Loading melts...", MessageSeverity.Low));
            });

            try
            {
                IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();

                Dispatcher.Invoke((ThreadStart)delegate
                {
                    foreach (MeltDto availableMelt in meltDtos)
                    {
                        MeltsAvailable.Add(availableMelt);
                    }
                    OnPropertyChanged("MeltsAvailable");

                    eventAggregator.GetEvent<BusyEvent>().Publish(false);
                    eventAggregator.GetEvent<StatusMessageEvent>().Publish(
                        new StatusMessage("Melts loaded", MessageSeverity.Low));
                });
            }
            catch (ApplicationException ex)
            {
                log.Error("An error occurred in MeltsViewModel when attempting to load melts", ex);

                Dispatcher.Invoke((ThreadStart)delegate
                {
                    MeltsAvailable.Clear();

                    eventAggregator.GetEvent<StatusMessageEvent>().Publish(
                        new StatusMessage("Melt data could not be loaded because an error occurred; " +
                            "see the application log for detail",
                            MessageSeverity.High));
                    eventAggregator.GetEvent<BusyEvent>().Publish(false);
                });
            }

        });

    }

يتم تعريف هذا في عنصر تحكم مستخدم WPF. Meltsavailived هو ObservableCollection من meltdtos. يعمل هذا الرمز بشكل جميل عند التشغيل في التطبيق نفسه.

المشكلة هي أنني أرغب في إنشاء اختبار وحدة ، باستخدام Nmock ، للتحقق من نتائج هذه الطريقة - على وجه التحديد ، أنه بمجرد أن يتم استدعاؤه ، فإن الخاصية المتوفرة تحتوي على بعض العناصر. ها هي طريقة الاختبار:

    [TestMethod]
    public void GetAvailableMeltsTest()
    {
        MeltDto mockMelt1 = new MeltDto();
        MeltDto mockMelt2 = new MeltDto();

        mockMelt1.MeltIdentifier = "TST0001";
        mockMelt2.MeltIdentifier = "TST0002";

        IList<MeltDto> availableMelts = new List<MeltDto>();
        availableMelts.Add(mockMelt1);
        availableMelts.Add(mockMelt2);

        Expect.Exactly(1).On(service).Method("GetActiveMelts").Will(Return.Value(availableMelts));


        MeltsViewModel vm = new MeltsViewModel(aggregator, logger, service, configManagerFactory); // All of these are mock objects

        vm.RefreshMelts();
        Thread.Sleep(millisecondDelayForEventPublish * 100);

        mockery.VerifyAllExpectationsHaveBeenMet();

        Assert.AreEqual(vm.MeltsAvailable.Count, 2);
        Assert.AreEqual(vm.MeltsAvailable[0].MeltIdentifier, "TST0001");
        Assert.AreEqual(vm.MeltsAvailable[1].MeltIdentifier, "TST0002");

    }

فشل الاختبار باستمرار على التأكيد الأول. Vm.Meltsavailaive فارغ في تلك المرحلة.

إذا قمت بتجريد كل الخيوط واتركها مثل:

    public void RefreshMelts()
    {
        MeltsAvailable.Clear();
        IList<MeltDto> meltDtos = meltingAppService.GetActiveMelts();
        foreach (MeltDto availableMelt in meltDtos)
        {
            MeltsAvailable.Add(availableMelt);
        }
        OnPropertyChanged("MeltsAvailable");
    }

يمر الاختبار.

لذلك ، من الواضح ، هناك شيء لا يعجبه في المواضيع-ولكن حتى تشغيل استثناءات Debug->-> استثناءات CLR-> ألقا ، وإيقاف تشغيل الكود الخاص بي ، لا أحصل على استثناءات على الإطلاق في RefreshMelts.

أغرب جزء هو أن المكالمة المرسل. invoke حيث أقوم بتحميل كائنات Meltdto في المجموعة المتاحة التي لا يبدو أنها تسمى أبدًا. يمكنني بطانية القسم بأكمله بنقاط التوقف ، ولم يتم ضربهم أبدًا. تعزيز thread.sleep الوقت في اختباري حتى أعلى من عشر ثوان لا يغير شيء.

لماذا ا؟ لماذا لا ينفذ هذا القسم ، لماذا لا يمكنني التدخل فيه أو اقتحامه ، لماذا لا أحصل على استثناءات ، لماذا يعمل بشكل جيد في التنفيذ ولكن ليس في الاختبار؟

شكرا جزيلا ستيف

هل كانت مفيدة؟

المحلول

المرسل هو حلقة رسالة مرتبطة بخيط تنفيذ. يقوم بمعالجة العناصر الموجودة في قائمة الانتظار عندما يكون الخيط الرئيسي في وضع الخمول. في اختبار الوحدة ، لا يحدث هذا أبدًا. الخيط مشغول ثم يخرج عند اكتمال الاختبار.

إذا كنت تستخدم Visual Studio لتشغيل الاختبارات الخاصة بك ، فيمكنك تشغيل تسليط الضوء على تغطية التعليمات البرمجية وسترى أن الكود داخل Dispatcher.invoke () لا يسمى أبدًا (سيتم عرضه باللون الأحمر).

يمكن استخدام DispatcherFrame لتشغيل المرسل لمعالجة الرسائل في قائمة الانتظار. أضف فئة المساعد التالية إلى مشروع اختبار الوحدة الخاص بك:

public static class DispatcherHelper 
{ 
    public static void DoEvents() 
    {
        DispatcherFrame frame = new DispatcherFrame(); 
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame);
        Dispatcher.PushFrame(frame); 
    } 

    private static object ExitFrame(object frame) 
    { 
        ((DispatcherFrame)frame).Continue = false; 
        return null; 
    } 
}

في نهاية الاختبار الخاص بك (قبل التأكيدات) استدعاء SPATCHERHELPER.Doevents (). سيؤدي ذلك إلى قيام المرسل بمعالجة الأحداث المتميزة ، مثل تلك التي تضيف عناصر إلى مجموعة View Model التي يمكن ملاحظتها. يمكنك بعد ذلك فحص خصائص نموذج العرض للتحقق من ضبطها بشكل صحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top