【发布时间】:2011-09-07 05:28:46
【问题描述】:
我定义了以下组合框:
<ComboBox x:Name="cmbCurrency"
ItemsSource="{Binding IsoCurrenciesList}"
DisplayMemberPath="Description"
SelectedValuePath="LocaleID"
SelectedValue="{Binding CurrencyId, Mode=TwoWay">
</ComboBox>
其中IsoCurrenciesList 是IEnumerable<IsoCurrency> - 我们定义并在视图模型中声明的类型为:
private IEnumerable<IsoCurrency> isoCurrenciesList;
public IEnumerable<IsoCurrency> IsoCurrenciesList
{
get { return isoCurrenciesList; }
set
{
isoCurrenciesList = value;
RaisePropertyChangedEvent("IsoCurrenciesList");
}
}
我的单元测试创建了视图和视图模型的实例,并在本地列表中设置了一些虚拟货币数据:
[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 属性)
[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's blog 上的指南,但无法通过绑定测试。
我已经尝试测试其他属性的绑定 - 简单的字符串、布尔值和整数,但在任一端所做的更改不会反映到另一端。
我唯一能想到的是,在将视图添加到 TestPanel 以“激活”绑定之后,我还需要执行另一个步骤,但我不知道它可能是什么。
更新
我应该指出,代码在实际应用中运行良好。根据 cmets(尤其是来自 Adam Sills 的 cmets),问题似乎出在我没有发布的代码中 - 即这是我们构建 XAML 的方式或存在差异我们设置DataContext 的方式。至少我可以将精力集中在(希望)正确的领域。
看来控件在视图中的位置确实很重要。 XAML 页面是这样的:
<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>
BusyIndicator 来自 Silverlight 工具包,SaveConfirmation 是我们编写的控件。
如果我在BusyIndicator 上测试IsBusy 绑定,它会按预期工作。但是,如果我在 SaveConfirmation 上测试 SavedState 绑定失败 - 我在测试中将 VendorSaved 属性设置为 true,但是当我获得控件时,绑定值为 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");
所以第一个测试通过了,但是第二个失败了。
我需要做些什么来确保元素的绑定一直沿树向下设置?
【问题讨论】:
-
我拿走了你的代码,消除了供应商,创建了一个非常简单的视图,只有一个网格“LayoutRoot”和一个 ComboBox,并且测试通过了很好(并且 Items.Count == 3)。
-
@Adam - 是的,
Vendor是在尝试测试其他绑定时留下的。它有效的事实是个好消息——它应该有效。所以看来问题出在我没有发布的内容中。 -
FWIW - XAML:textsnip.com/ec7b6a ViewModel:textsnip.com/cec377 测试:textsnip.com/d32a77
-
是只有unittest失败了,还是现实世界也失败了?
-
@Bubblewrap - 只有单元测试失败。一切都在现实世界中有效。鉴于 Adam Sills 让它与一个简单的视图和视图模型一起工作,我没有发布的代码中肯定有一些东西导致了问题。至少我现在知道去哪里看;)
标签: c# silverlight unit-testing xaml mvvm