2008-12-01 27 views
10

मैं माइक्रोसॉफ्ट टीम सिस्टम द्वारा प्रदान किए गए परीक्षण सूट का उपयोग करके अपने डब्ल्यूपीएफ डाटाबेसिंग का परीक्षण करने की कोशिश कर रहा हूं। मैं विंडो दिखाए बिना बाइंडिंग का परीक्षण करने में सक्षम होना चाहता हूं क्योंकि मेरे अधिकांश परीक्षण उपयोगकर्ता नियंत्रण के लिए होंगे और वास्तव में खिड़की पर नहीं। क्या यह संभव है या ऐसा करने का एक बेहतर तरीका है? अगर मैं खिड़की दिखाता हूं तो नीचे दिया गया कोड काम करता है, लेकिन यदि मैं नहीं करता, तो बाइंडिंग अपडेट नहीं होती है।यूनिट टेस्ट डब्ल्यूपीएफ बाइंडिंग

  Window1_Accessor target = new Window1_Accessor(); 
      UnitTestingWPF.Window1_Accessor.Person p = new UnitTestingWPF.Window1_Accessor.Person() { FirstName = "Shane" }; 
      Window1 window = (target.Target as Window1); 
      window.DataContext = p;   
      //window.Show(); //Only Works when I actually show the window 
      //Is it possible to manually update the binding here, maybe? Is there a better way? 
      Assert.AreEqual("Shane", target.textBoxFirstName.Text); //Fails if I don't Show() the window because the bindings aren't updated 

उत्तर

2

शेन, यदि आप वास्तव में चिंतित हैं, तो आप चुपचाप बाध्यकारी ब्रेकिंग कर रहे हैं, आपको बाध्यकारी निशान को कहीं भी जांचने पर देखना चाहिए। मैं यहाँ शुरू कर दूं:

http://blogs.msdn.com/mikehillberg/archive/2006/09/14/WpfTraceSources.aspx

उसके अलावा, मैं मुख्य रूप से automagic कि Gishu "उपसंहार" में उल्लेख किया है पर जा के कारण Gishu साथ सहमत हैं कि बाइंडिंग इकाई परीक्षण के लिए अच्छा उम्मीदवार नहीं हैं,। इसके बजाय यह सुनिश्चित करने पर ध्यान केंद्रित करें कि अंतर्निहित वर्ग सही तरीके से व्यवहार करता है।

ध्यान दें, भी, यहां तक ​​कि और अधिक मजबूत आप प्राप्त कर सकते हैं कि PresentationTraceSources वर्ग का उपयोग कर निशान:

http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.aspx

आशा है कि मदद करता है!

1

इसे नजरअंदाज करें।
इस प्रकार की घोषणात्मक मार्कअप शायद ही कभी टूट जाती है .. जब तक कि कोई मैनुअल में नहीं जाता और इसे खराब करता है। फिर भी, आप इसे मिनटों में ठीक कर सकते हैं। आईएमएचओ इस तरह के परीक्षणों को लिखने की लागत लाभ से कहीं अधिक है।

अद्यतन [दिसंबर 3,08]: ठीक है तो।
परीक्षण सिर्फ यह जांच रहा है कि टेक्स्टबॉक्स में बाध्यकारी की पथ संपत्ति के रूप में "फर्स्टनाम" मान है। यदि मैं वास्तविक डेटा स्रोत ऑब्जेक्ट में JustName को FirstName में बदलता/दोबारा बदलता हूं, तो परीक्षण अभी भी गुजरता है क्योंकि यह किसी अज्ञात प्रकार के विरुद्ध परीक्षण कर रहा है। (जब कोड टूट ग्रीन परीक्षण - TDD Antipattern: झूठे) अपने उद्देश्य की पुष्टि है कि प्रथम XAML में निर्दिष्ट किया गया है, तो

Assert.AreEqual("FirstName", txtBoxToProbe.GetBindingExpression(TextBox.TextProperty).ParentBinding.Path.Path); 

तुम सच में (इकाई परीक्षण के माध्यम से टूट बाइंडिंग को पकड़ने और करना आवश्यक है नहीं है यूआई दिखाना चाहते हैं), असली डेटा स्रोत का उपयोग करें ... थोड़ी देर के लिए संघर्ष किया और इसके साथ आया।

[Test] 
public void TestTextBoxBinding() 
{ 
    MyWindow w = new MyWindow(); 
    TextBox txtBoxToProbe = w.TextBox1; 
    Object obDataSource = w;    // use 'real' data source 

    BindingExpression bindingExpr = BindingOperations.GetBindingExpression(txtBoxToProbe, TextBox.TextProperty); 
    Binding newBind = new Binding(bindingExpr.ParentBinding.Path.Path); 
    newBind.Source = obDataSource; 
    txtBoxToProbe.SetBinding(TextBox.TextProperty, newBind); 

    Assert.AreEqual("Go ahead. Change my value.", txtBoxToProbe.Text); 
} 

उपसंहार: कुछ real covert stuffWindow.Show() करने के लिए कॉल में क्या हो रहा है। यह किसी भी तरह से जादुई रूप से DataItem प्रॉपर्टी सेट करता है जिसके बाद डेटा बाध्यकारी काम करना शुरू कर देता है।

// before show 
bindingExpr.DataItem => null 
bindingExpr.Status => BindingStatus.Unattached 

// after show 
bindingExpr.DataItem => {Actual Data Source} 
bindingExpr.Status => BindingStatus.Active 

एक बार बाध्यकारी सक्रिय है, मुझे लगता है आप इस तरह कोड के माध्यम से पाठ बॉक्स अपडेट मजबूर कर सकते हैं ..

txtBoxToProbe.GetBindingExpression(TextBox.TextProperty).UpdateTarget(); 

बार फिर, मैं इस दृष्टिकोण के खिलाफ मेरी अनिच्छा आवाज। एसटीए में चलाने के लिए एनयूनीट प्राप्त करना एक दर्द था ..

+2

हम एक कक्षा में गुण के लिए बाध्य कर रहे हैं, और वर्ग refactor हैं, XAML अभी भी संकलन होगा, लेकिन कोई अपवाद नहीं फेंक दिया जाएगा और हमारे अभी तक ऐप्स नहीं फ़ंक्शन ठीक बाइंडिंग गलत हो जाएगा के रूप में होगा। यह हमारे लिए पहले से ही एक मुद्दा रहा है इसलिए हम समाधान की तलाश में हैं। – NotDan

0

आप Guia को आजमा सकते हैं। इसके साथ आप अपने उपयोगकर्ता नियंत्रण को यूनिट-टेस्ट कर सकते हैं और जांच सकते हैं कि डेटा बाइंडिंग सही है या नहीं। हालांकि आपको खिड़की दिखाना है।

यहां एक उदाहरण है।यह आपके UserControl का एक नया उदाहरण शुरू करता है और इसके डेटाकॉन्टेक्स्ट को सेट करता है और तब जांचता है कि टेक्स्टबॉक्स सही मान पर सेट है या नहीं।

[TestMethod] 
    public void SimpleTest() 
    { 
     var viewModel = new SimpleControlViewModel() {TextBoxText = "Some Text"}; 

     customControl = CustomControl.Start<SimpleUserControl>((control) => control.DataContext = viewModel); 

     Assert.AreEqual("Some Text", customControl.Get<TextBox>("textbox1").Value); 

     customControl.Stop(); 
    } 
1

सलाह जोड़ना मैं कई एसओ पदों में आया, मैंने निम्नलिखित कक्षा लिखी जो WPF बाइंडिंग का परीक्षण करने के लिए बहुत अच्छी तरह से काम करता है।

public static class WpfBindingTester 
{ 
    /// <summary>load a view in a hidden window and monitor it for binding errors</summary> 
    /// <param name="view">a data-bound view to load and monitor for binding errors</param> 
    public static void AssertBindings(object view) 
    { 
     using (InternalTraceListener listener = new InternalTraceListener()) 
     { 
      ManualResetEventSlim mre = new ManualResetEventSlim(false); 

      Window window = new Window 
      { 
       Width = 0, 
       Height = 0, 
       WindowStyle = WindowStyle.None, 
       ShowInTaskbar = false, 
       ShowActivated = false, 
       Content = view 
      }; 

      window.Loaded += (_, __) => mre.Set(); 
      window.Show(); 

      mre.Wait(); 

      window.Close(); 

      Assert.That(listener.ErrorMessages, Is.Empty, listener.ErrorMessages); 
     } 
    } 

    /// <summary>Is the test running in an interactive session. Use with Assume.That(WpfBindingTester.IsAvailable) to make sure tests only run where they're able to</summary> 
    public static bool IsAvailable { get { return Environment.UserInteractive && Process.GetCurrentProcess().SessionId != 0; } } 


    private class InternalTraceListener : TraceListener 
    { 
     private readonly StringBuilder _errors = new StringBuilder(); 
     private readonly SourceLevels _originalLevel; 
     public string ErrorMessages { get { return _errors.ToString(); } } 

     static InternalTraceListener() { PresentationTraceSources.Refresh(); } 

     public InternalTraceListener() 
     { 
      _originalLevel = PresentationTraceSources.DataBindingSource.Switch.Level; 
      PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error; 
      PresentationTraceSources.DataBindingSource.Listeners.Add(this); 
     } 

     public override void Write(string message) {} 

     public override void WriteLine(string message) { _errors.AppendLine(message); } 

     protected override void Dispose(bool disposing) 
     { 
      PresentationTraceSources.DataBindingSource.Listeners.Remove(this); 
      PresentationTraceSources.DataBindingSource.Switch.Level = _originalLevel; 
      base.Dispose(disposing); 
     } 
    } 
} 
4

एक समाधान की तलाश में WPF अपवाद में बाध्यकारी त्रुटियों कन्वर्ट करने के लिए करते हैं, मैं पता लगा है कि यह भी एक इकाई परीक्षण परियोजना में इस्तेमाल किया जा सकता है।

तकनीक बहुत सरल है:

  1. प्राप्त एक TraceListener कि लॉगिंग
  2. के बजाय फेंकता PresentationTraceSources.DataBindingSource

है कि श्रोता जोड़े कृपया complete solution on GitHub देखते हैं, यह एक इकाई परीक्षण परियोजना भी शामिल है।

Failed test in Visual Studio

संबंधित मुद्दे