单元测试时应该如何处理嵌套的ViewModel?
我正在为我的项目中的ViewModel创建一些单元测试。我没有遇到任何问题,因为其中大多数都非常简单,但是当我在其他ViewModel中有一个新的(未完成的)ViewModel时遇到了问题。单元测试时应该如何处理嵌套的ViewModel?
public class OrderViewModel : ViewModelBase
{
public OrderViewModel(IDataService dataService, int orderId)
{
\\ ...
Payments = new ObservableCollection<PaymentViewModel>();
}
public ObservableCollection<PaymentViewModel> Payments { get; private set; }
public OrderStatus Status { ... } //INPC
public void AddPayment()
{
var vm = new PaymentViewModel();
payments.Add(vm);
// TODO: Subscribe to PaymentViewModel.OnPropertyChanged so that
// if the payment is valid, we update the Status to ready.
}
}
我想创建一个单元测试,这样,如果我的任何PaymentViewModel
的IsValid
属性更改和所有的人都不错,Status
应该OrderStatus.Ready
。我可以实现这个类,但是让我担心的是如果问题出现在PaymentViewModel
中,我的单元测试将会中断。
我不确定这是否正常,但它只是觉得我不应该担心PaymentViewModel
是否正常运行,以便我的单元测试OrderViewModel
是正确的。
public void GivenPaymentIsValidChangesAndAllPaymentsAreValid_ThenStatusIsReady()
{
var vm = new OrderViewModel();
vm.AddPayment();
vm.AddPayment();
foreach (var payment in vm.Payments)
{
Assert.AreNotEqual(vm.Status, OrderStatus.Ready);
MakePaymentValid(payment);
}
// Now all payments should be valid, so the order status should be ready.
Assert.AreEqual(vm.Status, OrderStatus.Ready);
}
的问题是,我怎么写MakePaymentValid
在保证了我PaymentViewModel的行为不会负我的单元测试影响这样的方式?因为如果是这样,那么我的单元测试就会失败,因为另一段代码不起作用,而不是我的代码。或者,如果PaymentViewModel
错误,它应该失败吗?我只是被撕裂,我不认为如果PaymentViewModel
有一个错误,我的OrderViewModel
测试应该失败。
我意识到我总是可以创建一个接口,就像我如何处理IDataService
一样,但是在我看来,让每个ViewModel都有一个接口并注入一些方法会有点矫枉过正?
说到单元测试,您绝对应该将测试与任何外部依赖分离开来。请记住,这并不意味着你必须通过一些界面;你会遇到你正在使用特定课程的情况,无论该课程是处于或不在你的控制之下。
想象一下,而不是你的榜样,你依靠DateTime.Now
。有些人会主张将其抽象成某种接口IDateTimeService
,这可以起作用。或者,您可以利用Microsoft Fakes:Shims &存根。
Microsoft Fakes将允许您创建Shim *实例。在这个主题上有很多需要解答的问题,但微软提供的图像说明了Fakes的使用超出了你的控制范围(它也包括了你的控制中的组件)。
通知如何要测试的组分(OrderViewModel
)应当从System.dll中(即DateTime.Now
),其它组分(PaymentViewModel
)和外部件中分离,以及(如果依赖于数据库或网络服务)。 Shim用于伪造类,而Stub用于伪造(嘲弄)界面。
一旦你添加一个假货组件,只需使用ShimPaymentViewModel
类,以提供您预计它应该的行为。如果出于某种原因,真正的PaymentViewModel
课程行为异常并且您的应用程序崩溃,您至少可以确信问题不是由OrderViewModel
引起的。当然,为了避免这种情况,您应该包含一些针对PaymentViewModel
的单元测试,以确保它的行为正确,无论其他类正在使用它或他们如何利用它。
TL; DR;
是的,当涉及到利用Microsoft Fakes进行测试时,完全隔离您的组件。哦,微软的假货和其他的框架很好地搭配,所以不要用它来表达你自己的选择;它与其他框架一起工作。
如果我理解正确。您可以为PaymentViewModel创建一个单独的测试,如果存在可能与PaymentViewModel中的IsValid属性相关的内容,则保留此项。另一方面,如果IsValid是一个没有任何业务逻辑的简单设置器,那么您将主要通过创建一个单独的测试来测试ObservableCollection,这似乎是多余的。 –