本文介绍了为什么我的 Silverlight XAML 绑定的单元测试失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义了以下组合框:

<ComboBox x:Name="cmbCurrency"
          ItemsSource="{Binding IsoCurrenciesList}"
          DisplayMemberPath="Description"
          SelectedValuePath="LocaleID"
          SelectedValue="{Binding CurrencyId, Mode=TwoWay">
</ComboBox>

其中 IsoCurrenciesList 是一个 IEnumerable - 由我们定义并在视图模型中声明为的类型:

Where IsoCurrenciesList is an IEnumerable<IsoCurrency> - the type being defined by us and declared in the view model as:

private IEnumerable<IsoCurrency> isoCurrenciesList;
public IEnumerable<IsoCurrency> IsoCurrenciesList
{
    get { return isoCurrenciesList; }
    set
    {
        isoCurrenciesList = value;
        RaisePropertyChangedEvent("IsoCurrenciesList");
    }
}

我的单元测试创​​建了一个视图和视图模型的实例,并在本地列表中设置了一些虚拟货币数据:

My unit test creates an instance of the view and view model and sets up some dummy currency data in a local list:

[TestInitialize]
public void TestInit()
{
    _target = new View();

    _viewModel = new ViewModel();

    var ukp = new IsoCurrency { Code = "GBP", Description = "Pound Sterling", LocaleID = 826 };
    var usd = new IsoCurrency { Code = "USD", Description = "US Dollar", LocaleID = 840 };
    var eur = new IsoCurrency { Code = "EUR", Description = "Euro", LocaleID = 978 };
    _currencies = new List<IsoCurrency> { ukp, usd, eur };

    GetUIElement<Grid>("LayoutRoot").DataContext = _viewModel;
}

private T GetUIElement<T>(string name) where T : UIElement
{
    return (T)_target.FindName(name);
}

然后调用测试方法.这应该设置货币 ComboBox.Items(通过 ItemsSource 属性)

Then the test method is called. This should set the currency ComboBox.Items (via the ItemsSource property)

[Asynchronous]
[TestMethod]
public void TestCurrencySelection()
{
    _target.Loaded += (s, e) =>
        {
            // Set the currency list explicitly
            _viewModel.IsoCurrenciesList = _currencies;

            var currencyCombo = GetUIElement<ComboBox>("cmbCurrency");
            // This assert fails as Items.Count == 0
            CollectionAssert.AreEquivalent(currencyCombo.Items, _currencies, "Failed to data-bind currencies.");

            EnqueueTestComplete();
        };

    TestPanel.Children.Add(_target);
}

我已遵循 Jeremy 上的准则Likeness 的博客,但我无法通过绑定测试.

I've followed the guidelines on Jeremy Likeness's blog but I can't get the bindings test to pass.

我尝试过测试其他属性的绑定 - 简单字符串、布尔值和整数,但在任一端所做的更改不会反映到另一端.

I've tried testing the bindings of other properties - simple strings, booleans and integers but the changes made at either end aren't reflected to the other.

我唯一能想到的是,在将视图添加到 TestPanel 以激活"绑定之后,我还需要执行另一个步骤,但我不知道它可以做什么

The only thing I can think of is that there is another step I need to do after adding the view to the TestPanel to "activate" the bindings, but I've no idea what it could be.

更新

我应该指出代码在实际应用中运行良好.根据评论(尤其是来自 Adam Sills 的评论),问题似乎出在我尚未发布的代码中 - 即它与我们构建 XAML 的方式有关,或者在我们设置 DataContext 的方式.至少我可以将精力集中在(希望)正确的领域.

I should point out that the code works fine in the actual application. Based on the comments (particularly those from Adam Sills) it looks like the problem lies in the code I haven't posted - i.e. it's something in the way we've structured the XAML or there's a difference in the way we set the DataContext. At least I can concentrate my efforts in (hopefully) the right area.

看起来控件在视图中的位置确实很重要.页面 XAML 是这样的:

It appears that the position of the control in the view does matter. The page XAML is something like this:

<Grid x:Name="LayoutRoot">
    <VisualStateManager.VisualStateGroups>
        ...
    </VisualStateManager.VisualStateGroups>

    <toolkit:BusyIndicator x:Name="activityControl"
                           IsBusy="{Binding IsBusy}"
                           BusyContent="{Binding BusyContent}" >
        <Grid>
            ... The page definition including sub grids, stack panels
                and the combo box I'm testing along with other controls

            <ops:SaveConfirmation Grid.Row="1" Margin="5"
                                  x:Name="saveConfirmation"
                                  SavedState="{Binding VendorSaved, Mode=TwoWay}" />
        </Grid>
    </toolkit:BusyIndicator/>
</Grid>

BusyIndi​​cator 是 Silverlight Toolkit 中的一个,SaveConfirmation 是我们编写的控件.

The BusyIndicator is the one from the Silverlight Toolkit and SaveConfirmation is a control we've written.

如果我测试 BusyIndi​​cator 上的 IsBusy 绑定是否按预期工作.但是,如果我在失败的 SaveConfirmation 上测试 SavedState 绑定 - 我在测试中将 VendorSaved 属性设置为 true 但是当我得到控制绑定值为false.

If I test the IsBusy binding on the BusyIndicator that works as expected. However, if I test the SavedState binding on the SaveConfirmation that fails - I set the VendorSaved property to true in the test but when I get the control the bound value is false.

var busyIndicator = GetUIElement<BusyIndicator>("activityControl");
Assert.AreEqual(busyIndicator.IsBusy, _viewModel.IsBusy, "Failed to data-bind busy indicator.");

var saveConfirmation = GetUIElement<SaveConfirmation>("saveConfirmation");
Assert.AreEqual(saveConfirmation.SavedState, _viewModel.VendorSaved, "Failed to data-bind saved state");

所以第一个测试通过,但第二个失败.

So the first test passes, but the second fails.

我需要做些什么来确保设置树中所有元素的绑定?

推荐答案

您已经包含了 ComboBox 的 XAML,但没有包含页面的其余部分.在您的测试中,您有 GetUIElement("LayoutRoot").DataContext = _viewModel;.在您所遵循的示例中,他定义了:

You've included the XAML for your ComboBox, but not the rest of your page. In your test you have GetUIElement<Grid>("LayoutRoot").DataContext = _viewModel;. In the example you're following, he defines:

<Grid x:Uid="LayoutRoot" x:Name="LayoutRoot" Background="White"
    DataContext="{Binding Source={StaticResource VMLocator},Path=Cascadia}">

然后他测试绑定的控件直接嵌套在该网格内.您的页面设置是否相同?

and then the controls on which he's testing the bindings are nested directly inside that grid. Is your page setup the same way?

这篇关于为什么我的 Silverlight XAML 绑定的单元测试失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 07:48
查看更多