using NewLife.Data;
using Xunit;
namespace XUnitTest.Core.Data;
/// <summary>分页参数测试</summary>
public class PageParameterTests
{
#region 构造函数测试
[Fact(DisplayName = "默认构造函数应设置正确的默认值")]
public void Constructor_Default_ShouldSetCorrectDefaults()
{
// Arrange & Act
var page = new PageParameter();
// Assert
Assert.Equal(1, page.PageIndex);
Assert.Equal(20, page.PageSize);
Assert.Null(page.Sort);
Assert.False(page.Desc);
Assert.Null(page.OrderBy);
Assert.Equal(-1, page.StartRow);
Assert.Equal(0, page.TotalCount);
Assert.False(page.RetrieveTotalCount);
Assert.Null(page.State);
Assert.False(page.RetrieveState);
}
[Fact(DisplayName = "复制构造函数应正确复制所有属性")]
public void Constructor_Copy_ShouldCopyAllProperties()
{
// Arrange - 注意:由于Sort会清空OrderBy,所以这里只测试Sort的情况
var original = new PageParameter
{
PageIndex = 2,
PageSize = 50,
Sort = "Name",
Desc = true,
StartRow = 100,
TotalCount = 1000,
RetrieveTotalCount = true,
State = "test state",
RetrieveState = true
};
// Act
var copy = new PageParameter(original);
// Assert
Assert.Equal(original.PageIndex, copy.PageIndex);
Assert.Equal(original.PageSize, copy.PageSize);
Assert.Equal(original.Sort, copy.Sort);
Assert.Equal(original.Desc, copy.Desc);
Assert.Null(copy.OrderBy); // Sort会清空OrderBy
Assert.Equal(original.StartRow, copy.StartRow);
Assert.Equal(original.TotalCount, copy.TotalCount);
Assert.Equal(original.RetrieveTotalCount, copy.RetrieveTotalCount);
Assert.Equal(original.State, copy.State);
Assert.Equal(original.RetrieveState, copy.RetrieveState);
}
[Fact(DisplayName = "复制构造函数会清空OrderBy(由于CopyFrom实现)")]
public void Constructor_Copy_WillClearOrderByDueToImplementation()
{
// Arrange - 只设置OrderBy,不设置Sort
var original = new PageParameter
{
PageIndex = 2,
PageSize = 50,
StartRow = 100,
TotalCount = 1000,
RetrieveTotalCount = true,
State = "test state",
RetrieveState = true
};
// 直接设置OrderBy而不通过Sort
original.OrderBy = "Custom ORDER BY";
// Act
var copy = new PageParameter(original);
// Assert - 由于CopyFrom的实现,OrderBy会被清空
Assert.Null(copy.OrderBy); // CopyFrom中Sort=pm.Sort会清空OrderBy
Assert.Null(copy.Sort); // 源对象的Sort确实是null
}
#endregion
#region Sort属性测试
[Fact(DisplayName = "设置Sort应清空OrderBy")]
public void Sort_Set_ShouldClearOrderBy()
{
// Arrange
var page = new PageParameter { OrderBy = "Custom ORDER BY" };
// Act
page.Sort = "Name";
// Assert
Assert.Equal("Name", page.Sort);
Assert.Null(page.OrderBy);
}
[Theory(DisplayName = "Sort应正确解析Asc方向")]
[InlineData("Name asc", "Name", false)]
[InlineData("Name ASC", "Name", false)]
[InlineData("Name Asc", "Name", false)]
[InlineData(" Name asc ", "Name", false)]
public void Sort_SetWithAsc_ShouldParseCorrectly(String input, String expectedSort, Boolean expectedDesc)
{
// Arrange
var page = new PageParameter();
// Act
page.Sort = input;
// Assert
Assert.Equal(expectedSort, page.Sort);
Assert.Equal(expectedDesc, page.Desc);
}
[Theory(DisplayName = "Sort应正确解析Desc方向")]
[InlineData("Name desc", "Name", true)]
[InlineData("Name DESC", "Name", true)]
[InlineData("Name Desc", "Name", true)]
[InlineData(" Name desc ", "Name", true)]
public void Sort_SetWithDesc_ShouldParseCorrectly(String input, String expectedSort, Boolean expectedDesc)
{
// Arrange
var page = new PageParameter();
// Act
page.Sort = input;
// Assert
Assert.Equal(expectedSort, page.Sort);
Assert.Equal(expectedDesc, page.Desc);
}
[Theory(DisplayName = "Sort不包含方向时应保持原字段")]
[InlineData("Name", "Name")]
[InlineData("CreateTime", "CreateTime")]
[InlineData("User.Name", "User.Name")]
public void Sort_SetWithoutDirection_ShouldKeepOriginal(String input, String expected)
{
// Arrange
var page = new PageParameter();
// Act
page.Sort = input;
// Assert
Assert.Equal(expected, page.Sort);
Assert.False(page.Desc); // 默认应为false
}
[Theory(DisplayName = "Sort包含逗号时不应解析方向")]
[InlineData("Name,Age desc", "Name,Age desc")]
[InlineData("Name asc, Age desc", "Name asc, Age desc")]
public void Sort_SetWithComma_ShouldNotParseDirection(String input, String expected)
{
// Arrange
var page = new PageParameter();
// Act
page.Sort = input;
// Assert
Assert.Equal(expected, page.Sort);
Assert.False(page.Desc); // 不应被解析
}
[Fact(DisplayName = "Sort设置为null或空应正确处理")]
public void Sort_SetNullOrEmpty_ShouldHandleCorrectly()
{
// Arrange
var page = new PageParameter();
// Act & Assert - null
page.Sort = null;
Assert.Null(page.Sort);
// Act & Assert - empty
page.Sort = "";
Assert.Equal("", page.Sort);
// Act & Assert - whitespace
page.Sort = " ";
Assert.Equal("", page.Sort); // 应被Trim为空
}
#endregion
#region PageCount属性测试
[Theory(DisplayName = "PageCount应正确计算页数")]
[InlineData(0, 20, 0)] // 总数为0时,页数为0(实际行为)
[InlineData(1, 20, 1)]
[InlineData(20, 20, 1)]
[InlineData(21, 20, 2)]
[InlineData(40, 20, 2)]
[InlineData(41, 20, 3)]
[InlineData(100, 30, 4)]
[InlineData(101, 30, 4)]
public void PageCount_Calculate_ShouldReturnCorrectValue(Int64 totalCount, Int32 pageSize, Int64 expectedPageCount)
{
// Arrange
var page = new PageParameter
{
TotalCount = totalCount,
PageSize = pageSize
};
// Act & Assert
Assert.Equal(expectedPageCount, page.PageCount);
}
[Fact(DisplayName = "PageSize为0时PageCount应返回1")]
public void PageCount_WhenPageSizeIsZero_ShouldReturnOne()
{
// Arrange
var page = new PageParameter
{
TotalCount = 100,
PageSize = 0
};
// Act & Assert
Assert.Equal(1, page.PageCount);
}
[Fact(DisplayName = "PageSize为负数时PageCount应返回1")]
public void PageCount_WhenPageSizeIsNegative_ShouldReturnOne()
{
// Arrange
var page = new PageParameter
{
TotalCount = 100,
PageSize = -10
};
// Act & Assert
Assert.Equal(1, page.PageCount);
}
#endregion
#region CopyFrom方法测试
[Fact(DisplayName = "CopyFrom应正确复制Sort相关属性")]
public void CopyFrom_WithSort_ShouldCopyCorrectly()
{
// Arrange
var source = new PageParameter
{
Sort = "Name",
Desc = true,
PageIndex = 3,
PageSize = 50,
StartRow = 200,
TotalCount = 2000,
RetrieveTotalCount = true,
State = "test state",
RetrieveState = true
};
var target = new PageParameter();
// Act
var result = target.CopyFrom(source);
// Assert
Assert.Same(target, result); // 应返回当前实例
Assert.Equal(source.Sort, target.Sort);
Assert.Equal(source.Desc, target.Desc);
Assert.Null(target.OrderBy); // Sort会清空OrderBy
Assert.Equal(source.PageIndex, target.PageIndex);
Assert.Equal(source.PageSize, target.PageSize);
Assert.Equal(source.StartRow, target.StartRow);
Assert.Equal(source.TotalCount, target.TotalCount);
Assert.Equal(source.RetrieveTotalCount, target.RetrieveTotalCount);
Assert.Equal(source.State, target.State);
Assert.Equal(source.RetrieveState, target.RetrieveState);
}
[Fact(DisplayName = "CopyFrom会清空OrderBy(由于实现原因)")]
public void CopyFrom_WillClearOrderByDueToImplementation()
{
// Arrange
var source = new PageParameter
{
PageIndex = 3,
PageSize = 50,
StartRow = 200,
TotalCount = 2000,
RetrieveTotalCount = true,
State = "test state",
RetrieveState = true
};
// 直接设置OrderBy而不设置Sort
source.OrderBy = "Custom ORDER BY";
var target = new PageParameter();
// Act
var result = target.CopyFrom(source);
// Assert - 由于CopyFrom实现中Sort=pm.Sort会清空OrderBy
Assert.Same(target, result); // 应返回当前实例
Assert.Null(target.OrderBy); // 被清空了
Assert.Null(target.Sort); // 源对象的Sort确实是null
Assert.Equal(source.PageIndex, target.PageIndex);
Assert.Equal(source.PageSize, target.PageSize);
Assert.Equal(source.StartRow, target.StartRow);
Assert.Equal(source.TotalCount, target.TotalCount);
Assert.Equal(source.RetrieveTotalCount, target.RetrieveTotalCount);
Assert.Equal(source.State, target.State);
Assert.Equal(source.RetrieveState, target.RetrieveState);
}
[Fact(DisplayName = "CopyFrom应体现Sort优先级高于OrderBy的特性")]
public void CopyFrom_WithBothSortAndOrderBy_ShouldPrioritizeSort()
{
// Arrange - 创建一个同时有Sort和OrderBy的源对象(通过特殊方式)
var source = new PageParameter();
source.OrderBy = "Custom ORDER BY"; // 先设置OrderBy
source.Sort = "Name"; // 这会清空OrderBy
source.OrderBy = "Custom ORDER BY"; // 重新设置OrderBy(这是实际可能的情况)
var target = new PageParameter();
// Act
var result = target.CopyFrom(source);
// Assert - 根据CopyFrom的实现,Sort会清空OrderBy
Assert.Same(target, result);
Assert.Equal("Name", target.Sort);
Assert.Null(target.OrderBy); // Sort会清空OrderBy
}
[Fact(DisplayName = "CopyFrom传入null应返回当前实例不变")]
public void CopyFrom_WithNull_ShouldReturnSelfUnchanged()
{
// Arrange
var original = new PageParameter
{
PageIndex = 2,
PageSize = 30,
Sort = "Original"
};
// Act
var result = original.CopyFrom(null);
// Assert
Assert.Same(original, result);
Assert.Equal(2, original.PageIndex);
Assert.Equal(30, original.PageSize);
Assert.Equal("Original", original.Sort);
}
#endregion
#region GetKey方法测试
[Fact(DisplayName = "GetKey应返回正确的键值格式")]
public void GetKey_ShouldReturnCorrectFormat()
{
// Arrange
var page = new PageParameter
{
PageIndex = 2,
TotalCount = 100,
PageSize = 20,
OrderBy = "Name DESC"
};
// Act
var key = page.GetKey();
// Assert
var expectedKey = $"2-5-Name DESC"; // PageIndex-PageCount-OrderBy
Assert.Equal(expectedKey, key);
}
[Fact(DisplayName = "GetKey在OrderBy为null时应正确处理")]
public void GetKey_WithNullOrderBy_ShouldHandleCorrectly()
{
// Arrange
var page = new PageParameter
{
PageIndex = 1,
TotalCount = 50,
PageSize = 10,
OrderBy = null
};
// Act
var key = page.GetKey();
// Assert
var expectedKey = "1-5-"; // PageIndex-PageCount-空OrderBy
Assert.Equal(expectedKey, key);
}
#endregion
#region IsValid方法测试
[Theory(DisplayName = "IsValid应正确验证有效参数")]
[InlineData(1, 20, true)]
[InlineData(1, 0, true)] // PageSize为0表示不分页,应该有效
[InlineData(10, 50, true)]
public void IsValid_WithValidParameters_ShouldReturnTrue(Int32 pageIndex, Int32 pageSize, Boolean expected)
{
// Arrange
var page = new PageParameter
{
PageIndex = pageIndex,
PageSize = pageSize
};
// Act & Assert
Assert.Equal(expected, page.IsValid());
}
[Theory(DisplayName = "IsValid应正确验证无效参数")]
[InlineData(0, 20, false)] // PageIndex不能为0
[InlineData(-1, 20, false)] // PageIndex不能为负数
[InlineData(1, -1, false)] // PageSize不能为负数
[InlineData(0, -1, false)] // 都无效
public void IsValid_WithInvalidParameters_ShouldReturnFalse(Int32 pageIndex, Int32 pageSize, Boolean expected)
{
// Arrange
var page = new PageParameter
{
PageIndex = pageIndex,
PageSize = pageSize
};
// Act & Assert
Assert.Equal(expected, page.IsValid());
}
#endregion
#region Reset方法测试
[Fact(DisplayName = "Reset应将所有属性重置为默认值")]
public void Reset_ShouldResetAllPropertiesToDefaults()
{
// Arrange
var page = new PageParameter
{
PageIndex = 5,
PageSize = 100,
Sort = "Name",
OrderBy = "Custom ORDER BY",
Desc = true,
StartRow = 200,
TotalCount = 1000,
RetrieveTotalCount = true,
State = "test state",
RetrieveState = true
};
// Act
page.Reset();
// Assert
Assert.Equal(1, page.PageIndex);
Assert.Equal(20, page.PageSize);
Assert.Null(page.Sort);
Assert.Null(page.OrderBy);
Assert.False(page.Desc);
Assert.Equal(-1, page.StartRow);
Assert.Equal(0, page.TotalCount);
Assert.False(page.RetrieveTotalCount);
Assert.Null(page.State);
Assert.False(page.RetrieveState);
}
#endregion
#region 边界和异常测试
[Fact(DisplayName = "大数值应正确处理")]
public void LargeValues_ShouldHandleCorrectly()
{
// Arrange & Act
var page = new PageParameter
{
PageIndex = Int32.MaxValue,
PageSize = Int32.MaxValue,
TotalCount = Int64.MaxValue,
StartRow = Int64.MaxValue
};
// Assert
Assert.Equal(Int32.MaxValue, page.PageIndex);
Assert.Equal(Int32.MaxValue, page.PageSize);
Assert.Equal(Int64.MaxValue, page.TotalCount);
Assert.Equal(Int64.MaxValue, page.StartRow);
Assert.True(page.IsValid());
}
[Fact(DisplayName = "复杂排序字段解析应正确处理")]
public void ComplexSortField_ShouldParseCorrectly()
{
// Arrange
var page = new PageParameter();
// Act & Assert - 包含点号的字段名
page.Sort = "User.Name desc";
Assert.Equal("User.Name", page.Sort);
Assert.True(page.Desc);
// Act & Assert - 包含下划线的字段名
page.Sort = "created_time asc";
Assert.Equal("created_time", page.Sort);
Assert.False(page.Desc);
// Act & Assert - 纯数字字段名
page.Sort = "123 desc";
Assert.Equal("123", page.Sort);
Assert.True(page.Desc);
}
[Fact(DisplayName = "State属性应支持任意对象类型")]
public void State_ShouldSupportAnyObjectType()
{
// Arrange
var page = new PageParameter();
var complexState = new { Filter = "active", UserId = 123, Tags = new[] { "tag1", "tag2" } };
// Act
page.State = complexState;
// Assert
Assert.Equal(complexState, page.State);
}
#endregion
#region 分页模式测试
[Fact(DisplayName = "StartRow模式应正确设置")]
public void StartRowMode_ShouldSetCorrectly()
{
// Arrange
var page = new PageParameter
{
PageIndex = 5,
StartRow = 100
};
// Act & Assert
Assert.Equal(5, page.PageIndex); // PageIndex仍然保留
Assert.Equal(100, page.StartRow); // StartRow应该设置
}
[Fact(DisplayName = "不同分页模式的有效性验证")]
public void DifferentPagingModes_ValidityCheck()
{
// Arrange & Act & Assert - 正常PageIndex模式
var pageIndexMode = new PageParameter { PageIndex = 2, PageSize = 20 };
Assert.True(pageIndexMode.IsValid());
// Arrange & Act & Assert - StartRow模式
var startRowMode = new PageParameter { PageIndex = 1, PageSize = 20, StartRow = 40 };
Assert.True(startRowMode.IsValid());
// Arrange & Act & Assert - 不分页模式
var noPagingMode = new PageParameter { PageIndex = 1, PageSize = 0 };
Assert.True(noPagingMode.IsValid());
}
#endregion
#region 排序优先级测试
[Fact(DisplayName = "OrderBy优先级应高于Sort")]
public void OrderBy_ShouldHaveHigherPriorityThanSort()
{
// Arrange
var page = new PageParameter
{
Sort = "Name",
OrderBy = "Custom ORDER BY"
};
// Act - 设置Sort应清空OrderBy
page.Sort = "Age";
// Assert
Assert.Equal("Age", page.Sort);
Assert.Null(page.OrderBy);
// Act - 重新设置OrderBy
page.OrderBy = "Another Custom ORDER BY";
// Assert
Assert.Equal("Age", page.Sort); // Sort保持不变
Assert.Equal("Another Custom ORDER BY", page.OrderBy);
}
#endregion
#region 扩展功能测试
[Fact(DisplayName = "应正确处理扩展查询标志")]
public void ExtendedQuery_FlagsHandling()
{
// Arrange
var page = new PageParameter();
// Act & Assert - 默认状态
Assert.False(page.RetrieveTotalCount);
Assert.False(page.RetrieveState);
// Act & Assert - 设置标志
page.RetrieveTotalCount = true;
page.RetrieveState = true;
Assert.True(page.RetrieveTotalCount);
Assert.True(page.RetrieveState);
}
[Fact(DisplayName = "应正确处理数据权限State")]
public void DataPermission_StateHandling()
{
// Arrange
var page = new PageParameter();
var permissionData = new
{
UserId = 123,
Roles = new[] { "Admin", "User" },
Filters = new Dictionary<String, Object>
{
["Department"] = "IT",
["Level"] = 5
}
};
// Act
page.State = permissionData;
page.RetrieveState = true;
// Assert
Assert.Equal(permissionData, page.State);
Assert.True(page.RetrieveState);
}
[Fact(DisplayName = "测试Sort设置为null时的行为")]
public void Sort_SetToNull_ShouldClearOrderBy()
{
// Arrange
var page = new PageParameter();
page.OrderBy = "Custom ORDER BY";
// Act - 设置Sort为null也会触发setter
page.Sort = null;
// Assert
Assert.Null(page.Sort);
Assert.Null(page.OrderBy); // OrderBy应该被清空
}
#endregion
}
|