How to call setter for WPF text field in NUnit test

I am trying to write System Tests in NUnit and I want to invoke user interface using user interface automation from ms.

For some reason, my Invokes fails - I found a few tips on the Internet that put me in a state where I can write a compilation test, but my statement fails.

Here is a compiled minimum example. My problem is the failed test in this example.

XAML application

<Application x:Class="InvokeTest.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:InvokeTest" Startup="Application_Startup"/> 

CS app

 using System.Windows; namespace InvokeTest { public partial class App : Application { private void Application_Startup(object sender, StartupEventArgs e) { var view = new MainWindow(); var viewmodel = new MainWindowViewModel(); view.DataContext = viewmodel; view.Show(); } } } 

XAML window

 <Window x:Class="InvokeTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:InvokeTest" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <TextBox x:Name="MyTextBox" x:FieldModifier="public" Text="{Binding TextProperty, UpdateSourceTrigger=PropertyChanged}" /> </Window> 

CS window

 using NUnit.Framework; using System.Diagnostics; using System.Threading; using System.Windows; using System.Windows.Automation.Peers; using System.Windows.Automation.Provider; using System.Windows.Controls; namespace InvokeTest { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class MainWindowViewModel { string textfield; public string TextProperty { get { DebugLog("getter"); return textfield; } set { textfield = value; DebugLog("setter"); } } private void DebugLog(string function) { Debug.WriteLine(ToString() + " " + nameof(TextProperty) + " " + function + " was called. value: '" + textfield ?? "<null>" + "'"); } [TestFixture, Apartment(ApartmentState.STA)] public class WPFTest { MainWindow view; MainWindowViewModel viewmodel; [SetUp] public void SetUp() { view = new MainWindow(); viewmodel = new MainWindowViewModel(); view.DataContext = viewmodel; } [Test] public void SetTextBox_NoAutomation() { string expected = "I want to set this"; view.MyTextBox.Text = expected; Assert.AreEqual(expected, viewmodel.TextProperty); /* Test Name: SetTextBox_NoAutomation Test Outcome: Failed Result Message: Expected: "I want to set this" But was: null */ } [Test] public void SetTextBox_UIAutomation() { string expected = "I want to set this"; SetValue(view.MyTextBox, expected); Assert.AreEqual(expected, viewmodel.TextProperty); /* Test Name: SetTextBox_UIAutomation Test Outcome: Failed Result Message: Expected: "I want to set this" But was: null */ } private static void SetValue(TextBox textbox, string value) { TextBoxAutomationPeer peer = new TextBoxAutomationPeer(textbox); IValueProvider provider = peer.GetPattern(PatternInterface.Value) as IValueProvider; provider.SetValue(value); } } } } 

EDIT # 1: @Nkosi noted that there was a communication failure in my xaml EDIT # 2: Added a bit of a boiler for manual testing, and also added custom code that shows behavior without uiautomation. This is just a side signal, the essence of which lies in this matter.

+6
source share
2 answers

I need to show a window. I assume that he should start the message pump.

If someone can provide details of this, I will reply to this answer as an accepted answer.

 using NUnit.Framework; using System.Diagnostics; using System.Threading; using System.Windows; using System.Windows.Automation.Peers; using System.Windows.Automation.Provider; using System.Windows.Controls; namespace InvokeTest { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class MainWindowViewModel { string textfield; public string TextProperty { get { DebugLog("getter"); return textfield; } set { textfield = value; DebugLog("setter"); } } private void DebugLog(string function) { Debug.WriteLine(ToString() + " " + nameof(TextProperty) + " " + function + " was called. value: '" + textfield ?? "<null>" + "'"); } [TestFixture, Apartment(ApartmentState.STA)] public class WPFTest { MainWindow view; MainWindowViewModel viewmodel; [SetUp] public void SetUp() { view = new MainWindow(); viewmodel = new MainWindowViewModel(); view.DataContext = viewmodel; view.Show(); } [TearDown] public void TearDown() { view.Close(); view.DataContext = null; view = null; viewmodel = null; } [Test] public void SetTextBox_NoAutomation() { string expected = "I want to set this"; view.MyTextBox.Text = expected; Assert.AreEqual(expected, viewmodel.TextProperty); } [Test] public void SetTextBox_UIAutomation() { string expected = "I want to set this"; SetValue(view.MyTextBox, expected); Assert.AreEqual(expected, viewmodel.TextProperty); } private void SetValue(TextBox textbox, string value) { TextBoxAutomationPeer peer = new TextBoxAutomationPeer(textbox); IValueProvider provider = peer.GetPattern(PatternInterface.Value) as IValueProvider; provider.SetValue(value); } } } } 
0
source

In fact, you can call the TextBox.Text Property .

 view.MyTextBox.Text = expected; 

In your view, you also bind to the Text property in your view model, while the view model in your test has the MyTextBox property. One or the other must be updated to match.

 public class MainWindowViewModel { public string Text { get; set; } } [TestFixture, Apartment(ApartmentState.STA)] public class WPFTest { [Test] public void SetTextBox() { //Arrange var expected = "I want to set this"; var view = new MainWindow(); var viewmodel = new MainWindowViewModel(); view.DataContext = viewmodel; //Act view.MyTextBox.Text = expected; //Assert Assert.AreEqual(expected, viewmodel.Text); } } 
+2
source

All Articles