use*_*238 3 c# unit-testing caliburn.micro
我正在MVVM中迈出第一步。
我正在使用Caliburn.Micro作为我的MVVM框架。
我有以下代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Globalization;
using Caliburn.Micro;
namespace MY_PROJECT.ViewModels
{
[Export(typeof(MainViewModel))]
public class MainViewModel : Screen
{
private readonly IWindowManager _windowManager = null;
private readonly IEventAggregator _events;
private string _title = string.Empty;
private WindowState _windowState = WindowState.Normal;
public string Title
{
get
{
return _title;
}
set
{
_title = value;
NotifyOfPropertyChange(() => Title);
}
}
public WindowState WindowState
{
get
{
return _windowState;
}
set
{
_windowState = value;
NotifyOfPropertyChange(() => WindowState);
}
}
public void ChangeTittle(string title)
{
Title = title;
}
public void ToggleWindowState()
{
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
}
[ImportingConstructor]
public MainViewModel(IWindowManager windowManager, IEventAggregator events)
{
_windowManager = windowManager;
_events = events;
_events.Subscribe(this);
}
}
Run Code Online (Sandbox Code Playgroud)
我现在想编写一些简单的单元测试来测试我的视图模型。
关于如何做的任何建议?
Caliburn.Micro的文档似乎缺少此信息。
好的,您只需要通过IoC容器运行整个应用程序并引导整个过程,这样就可以为所有接口获得实际的具体实现。不利的一面是,您将需要所有可用的东西(数据库,Web服务等),并且如果您几乎需要所有应用程序都在运行,则测试该应用程序可能会更加困难(并且由于实际工作正在执行,因此执行测试的速度可能会慢得多)完成)。如果您可以轻松地走这条路线,那么请务必使用它。
或者,您可以通过使用模拟框架(例如Moq)使用模拟或存根来模拟对象的行为/状态
使用Moq,您可以设置测试环境,以使接口和类由Mock<T>(模拟对象)表示,并为其指定行为。然后在您的行为中测试该行为ViewModels
这是使用Moq和NUnit进行MainViewModel当前测试的一组示例测试:
// Decorate with test fixture attribute so NUnit knows it's a test
[TestFixture]
class MainViewModelTests
{
// The interfaces/instances you will need to test with - this is your test subject
MainViewModel _mainVM;
// You can mock the other interfaces:
Mock<IWindowManager> _windowManager;
Mock<IEventAggregator> _eventAggregator;
// Setup method will run at the start of each test
[SetUp]
public void Setup()
{
// Mock the window manager
_windowManager = new Mock<IWindowManager>();
// Mock the event aggregator
_windowManager = new Mock<IEventAggregator>();
// Create the main VM injecting the mocked interfaces
// Mocking interfaces is always good as there is a lot of freedom
// Use mock.Object to get hold of the object, the mock is just a proxy that decorates the original object
_mainVM = new MainViewModel(_windowManager.Object, _eventAggregator.Object);
}
// Create a test to make sure the VM subscribes to the aggregator (a GOOD test, I forget to do this a LOT and this test gives me a slap in the face)
[Test]
public void Test_SubscribedToEventAggregator()
{
// Test to make sure subscribe was called on the event aggregator at least once
_eventAggregator.Verify(x => x.Subscribe(_mainVM));
}
// Check that window state toggles ok when it's called
[Test]
public void Test_WindowStateTogglesCorrectly()
{
// Run the aggregator test at the start of each test (this will run as a 'child' test)
Test_SubscribedToEventAggregator();
// Check the default state of the window is Normal
Assert.True(_mainVM.WindowState == WindowState.Normal);
// Toggle it
_mainVM.ToggleWindowState();
// Check it's maximised
Assert.True(_mainVM.WindowState == WindowState.Maximised);
// Check toggle again for normal
_mainVM.ToggleWindowState();
Assert.True(_mainVM.WindowState == WindowState.Normal);
}
// Test the title changes correctly when the method is called
[Test]
public void Test_WindowTitleChanges()
{
Test_SubscribedToEventAggregator();
_mainVM.ChangeTitle("test title");
Assert.True(_mainVM.Title == "test title");
}
}
Run Code Online (Sandbox Code Playgroud)
您可以看到如何测试状态和行为,当调用诸如VM之类的VM方法时,我期望某个VM状态ChangeTitle,并且还期望有一种行为(我希望Subscribe(X)在每次测试开始时至少在聚合器上调用一次) 。
[SetUp]在每次测试开始时,都会调用带有修饰符的方法。有拆卸和其他方法(包括设置整个测试夹具的方法,即每个夹具只运行一次)
这里的关键是,对于CM,您实际上不需要在事件聚合器中模拟任何行为,因为CM希望您IHandle<T>为事件聚合器消息实现。使这些订阅者方法成为接口实现意味着您将在对象上具有公共方法,可以调用这些方法来模拟事件聚合器调用。
因此,例如,您可以使用
public class MainViewModel : IHandle<someEventMessageArgument> // (this is your subscriber interface)
{
// (and this is the corresponding method)
public void Handle(someEventMessageArgument message)
{
// do something useful maybe change object state or call some methods
}
}
// Test the method - you don't need to mock any event aggregator behaviour since you have tested that the VM was subscribed to the aggregator. (OK CM might be broken but that's Robs problem :))
[Test]
Test_SomeEventDoesWhatYouAreExpecting()
{
_mainVM.Handle(someEventMessageArgument);
// Assert that what was supposed to happen happened...
Assert.True(SomethingHappened);
}
Run Code Online (Sandbox Code Playgroud)
在此处查看起订量快速入门:
http://code.google.com/p/moq/wiki/QuickStart
| 归档时间: |
|
| 查看次数: |
3687 次 |
| 最近记录: |