最近我被安排到一个新的团队工作,负责人告诉我为他们写的代码写单元测试。我真的不知道从哪里开始。这个应用程序是用C#写的WPF。我对WPF和C#都是新手。他们提到使用Xunit。
这是这个类的前两个函数。我必须对保护函数和公共函数进行单元测试,
类类型为public class DataTableModel<T> : ViewModelBase
public DataTableModel()
{
//Setup Drag and Drop Commands:
RecordReceivedCommand = new DataTableReceivedCommand<T>(this);
RecordRemovedCommand = new DataTableRemovedCommand<T>(this);
RecordInsertedCommand = new DataTableInsertedCommand<T>(this);
View = CollectionViewSource.GetDefaultView(Records);
}
/// <summary>
/// This method sets up the properties for the table. By default, the first DisplayOption is selected, no search criteria is applies, and only 10 records should be returned.
/// </summary>
/// <param name="displayOption">The selected display option</param>
protected void InstantiateTable(int displayOption = 0)
{
_displayOption = displayOption;
_searchCriteria = "";
_displayAmount = "10";
_currentPage = 1;
_userMessage = "Retrieving data...";
TriggerUpdate();
}
这些函数是从上面调用的,所以我想我应该包括它们。
/// <summary>
/// This method is responsible for handling the updates to the recordset that the DataGrid will display.
/// Upon changes to the search criteria, display amount, display option and the current page, this method will be triggered
/// </summary>
/// <param name="resetPage">Inidicates whether the grid should return to page 1.</param>
protected void TriggerUpdate(bool resetPage = false)
{
_currentPage = resetPage ? 1 : _currentPage; //only reset to the first page if indicated
UserMessage = "Retrieving data...";
//Retrieve the records if the delegate has been set
GetRecords?.Invoke();
UserMessage = Records.Count == 0 ? "No data found" : "";
Message_ZIndex = !String.IsNullOrWhiteSpace(UserMessage) ? 1 : -1;
//update the page navigations button's settings when the pages are reset
UpdatePagination();
}
/// <summary>
/// Update the ability to navigate through the datatable's pages.
/// Upon changes the the search criteria, display amount, display option, the number of pages and the current page, this method will be
/// triggered
/// </summary>
private void UpdatePagination()
{
if (Pages > 1)
{
if (_currentPage == 1)
{
GoToFirstPage = false;
GoToPrevPage = false;
GoToNextPage = true;
GoToLastPage = true;
}
else if (_currentPage == Pages)
{
GoToFirstPage = true;
GoToPrevPage = true;
GoToNextPage = false;
GoToLastPage = false;
}
else
{
GoToFirstPage = true;
GoToPrevPage = true;
GoToNextPage = true;
GoToLastPage = true;
}
}
else
{
GoToFirstPage = false;
GoToPrevPage = false;
GoToNextPage = false;
GoToLastPage = false;
}
}
/// <summary>
/// Get's the information for the datatable's columns
/// (NOTE: This method is currently only called via ".Invoke" within the DataTable control.)
/// </summary>
/// <returns>A List of the DataTableDisplay attributes for the columns in the table</returns>
public List<DataTableDisplay> GetTableColumnInformation()
{
List<DataTableDisplay> attributes = new List<DataTableDisplay>();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach(PropertyInfo property in properties)
{
DataTableDisplay attr = property.GetCustomAttribute<DataTableDisplay>(false);
if (attr != null && !String.IsNullOrWhiteSpace(attr.ColumnTitle))
{
attributes.Add(attr);
}
}
return attributes;
}
首先我想测试构造函数,但后来我不知道如何检查命令变量,所以我转移到InstantiateTable
函数。这是我得到的。仍然必须创建对象,所以使用构造函数,但当我试图调用x.InstantiateTable()
时,我注意到它是受保护的,所以我不能这样做。
用于创建DataTableModel对象的测试用例。它具有动态类型,因此我将其设为int。
[Fact]
public void DataTableModel_Created()
{
DataTableModel<int> x = new DataTableModel<int>();
Assert.Equal(0, x.DisplayOption);
Assert.Equal("", x.SearchCriteria);
Assert.Equal("10", x.DisplayAmount);
Assert.Equal(1, x.CurrentPage);
Assert.Equal("Retrieving data...", x.UserMessage);
}
另一个受保护的功能,我必须进行单元测试。
protected List<T> UpdateTable(List<T> data)
{
_totalCount = data.Count;
int recordLimit = String.IsNullOrEmpty(DisplayAmount) ? 0 : Convert.ToInt32(DisplayAmount);
int startingRecord = recordLimit == 0 ? 0 : (_currentPage == 1 ? 1 : 1 + (recordLimit * (_currentPage - 1)));
int recordsToSkip = (CurrentPage - 1) * recordLimit;
int endingRecord = recordLimit == 0 ? 0 : recordLimit > _totalCount ? _totalCount : startingRecord + recordLimit - 1;
Pages = recordLimit == 0 ? 0 : _totalCount <= recordLimit ? 1 : _totalCount % recordLimit > 0 ? (_totalCount / recordLimit) + 1 : _totalCount / recordLimit;
List<T> displayRecords = data.Skip(recordsToSkip).Take(recordLimit).ToList();
DisplayMessage = endingRecord <= _totalCount ? $"Showing {(displayRecords.Count == 0 ? 0 : startingRecord)} to {endingRecord} of {_totalCount} entries" : $"Showing {startingRecord} to {_totalCount} of {_totalCount} entries";
return displayRecords;
}
还有一个委托函数?我应该测试
public delegate List<T> Filter(List<T> data);
我不知道如何处理。我在大学做的几个单元测试是基本对象,没有调用其他对象。我读过关于模拟和存根对象的文章,我认为模拟数据库来填充表可能是好的。
1条答案
按热度按时间ars1skjm1#
不要对函数进行单元测试。对视图模型进行单元测试。
视图模型公开由XAML绑定到GUI控件的属性和命令,以便用户可以与它们交互。
所有这些属性和命令都已经是
public
,否则它们在XAML中是不可见的,因此您的测试也可以访问它们。大多数C#程序员在将
private
和protected
转换为public
,或者转换为internal
然后使用InternalsVisibleTo
之前不会三思而后行,但在我看来,这都是错误的。因此,我们必须进行黑箱测试,而不是白箱测试。在WPF中测试视图模型时,这意味着您应该只测试向XAML公开的内容。
因此,您的测试应该为视图模型属性设置值,就好像这些值是由GUI控件设置的一样,调用视图模型命令就好像这些命令是由GUI按钮触发的一样。
然后,您的测试应该只检查视图模型属性的值是如何变化的,这就是用户在屏幕上看到的。