想了一个礼拜,究竟是先实现些具体功能呢,还是继续完善TDD,还是先后者吧:具体功能无非就是些api的调用,wp7的twiter或者围脖的例子也有一些了,也不少我这一篇:)
1. 准备几个基本类,status,user和SinaService接口
public class User
{
public ulong Id { get ; set ; }
public string ScreenName { get ; set ; }
public string ImageUrl { get ; set ; }
public string Name { get ; set ; }
public string Url { get ; set ; }
public string Description { get ; set ; }
public string Location { get ; set ; }
public int Followers { get ; set ; }
public int Friends { get ; set ; }
public DateTime CreatedAt { get ; set ; }
}
public class Status
{
public Status()
{
User = new User();
}
public DateTime CreatedAt { get ; set ; }
public ulong Id { get ; set ; }
public string Text { get ; set ; }
public string Source { get ; set ; }
public User User { get ; set ; }
public bool Favorited { get ; set ; }
public int RetweetCount { get ; set ; }
public bool Retweeted { get ; set ; }
}
/// <summary>
/// A simple Sina service interface
/// </summary>
public interface ISinaService
{
/// <summary>
/// Get statuses from sina weibo
/// </summary>
/// <param name="onGetStatusesCompleted"> the callback method </param>
/// <param name="onError"></param>
/// <param name="onFinally"></param>
void GetStatuses(Action < IEnumerable < Status >> onGetStatusesCompleted = null , Action < Exception > onError = null , Action onFinally = null );
}
status和user类的相应测试俺就偷懒不写了,读者有兴趣可以自己试试!
2. 修改下MainPageViewModel, 加入SinaService接口和HomeList,前者用来调用sina的接口取得数据,后者是最新微博的容器。注意把它们设置为internal,方便测试项目调用,还要添加如下一行在AssemblyInfo.cs中:
[assembly: InternalsVisibleTo("WeiBo7.Test")]
public class MainPageViewModel : ViewModelBase
{
internal readonly ISinaService SinaService;
private bool _isHomeRefreshing = false ;
public MainPageViewModel()
{
SinaService = new SinaService();
HomeList = new ObservableCollection < Status > ();
}
public ObservableCollection < Status > HomeList { get ; internal set ; }
/// <summary>
/// Indicates whether there is an indeterminate operation in progress
/// </summary>
public bool IsHomeRefreshing
{
get { return _isHomeRefreshing; }
set
{
if (value != _isHomeRefreshing)
{
_isHomeRefreshing = value;
OnNotifyPropertyChanged( " IsHomeRefreshing " );
}
}
}
}
3. 现在转到测试项目,先加入一个TestInitialize方法,在所有的测试方法前做些准备工作:
private MainPageViewModel _mainViewModel;
[TestInitialize]
public void Initialize()
{
_mainViewModel = new MainPageViewModel();
}
还可以加入一个[TestCleanup]方法:
[TestCleanup]
public void CleanUp()
{
}
目前没干什么事情,但对于任何一个测试方法,执行顺序是TestInitialize->test method->TestCleanup, 这样保证每个测试方法是彼此独立,互不影响,不用在每个测试方法里面都初始化,节省些代码。
4. 在MainPageViewModelTests先添加一个negative test, 看下这个类如何应对NullInstance
[TestMethod]
[ExpectedException( typeof (NullReferenceException))]
public void NullInstance()
{
_mainViewModel = null ;
bool x = _mainViewModel.IsHomeRefreshing;
}
5. 测试初始化是否成功
[TestMethod]
public void Init_MainPageViewModel_Success()
{
Assert.IsNotNull(_mainViewModel);
Assert.IsNotNull(_mainViewModel.HomeList);
Assert.IsNotNull(_mainViewModel.SinaService);
Assert.IsInstanceOfType(_mainViewModel, typeof (INotifyPropertyChanged));
}
6. 测试当添加一个item到HomeList时,是否CollectionChanged被fire
[TestMethod]
public void AddItem_HomeList_RaisesCollectionChanged()
{
bool changeObserved = false ;
_mainViewModel.HomeList.CollectionChanged +=
(s, e) =>
{
changeObserved = true ;
Assert.AreEqual(NotifyCollectionChangedAction.Add, e.Action);
Assert.AreEqual( 1 , e.NewItems.Count, " only should be +1 item " );
};
_mainViewModel.HomeList.Add( new Status());
Assert.IsTrue(changeObserved);
}