Here is my test:
[TestFixture]
public class DisplayingPageLinks
{
[Test]
public void Can_Generate_Links_To_Other_Pages()
{
//Arrange: We're going to extend the Html helper class.
//It doesn't matter if the variable we use is null 开发者_StackOverflow
HtmlHelper html = null;
PagingInfo pagingInfo = new PagingInfo(){
CurrentPage = 2,
TotalItems = 28,
ItemsPerPage = 10
};
Func<int, String> pageUrl = i => "Page" + 1;
//Act: Here's how it should format the links.
MvcHtmlString result = html.PageLinks(pagingInfo, pageUrl);
//Assert:
result.ToString().ShouldEqual(@"<a href=""Page1"">1</a><a href=""Page2"">2</a><a href=""Page3"">3</a>");
}
}
Here is the PageLinks extension method:
public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo, Func<int,string> pageUrl)
{
StringBuilder result = new StringBuilder();
for (int i = 1; i < pagingInfo.TotalPages; i++)
{
TagBuilder tag = new TagBuilder("a");
tag.MergeAttribute("href", pageUrl(i));
tag.InnerHtml = i.ToString();
if (i == pagingInfo.CurrentPage)
{
tag.AddCssClass("selected");
}
result.Append(tag.ToString());
}
return MvcHtmlString.Create(result.ToString());
}
Finally here is the result for the running test:
SportsStore.UnitTests.DisplayingPageLinks.Can_Generate_Links_To_Other_Pages: Expected string length 63 but was 59. Strings differ at index 24.
Expected: "123" But was: "12" -----------------------------------^
The error doesn't copy the way it's shown in the GUI - sorry.
Can you give me some suggestions as to why NUnit is saying it receives something I don't expect it to give out.
According to what I'm reading in the PageLinks extension method, it seems that the markup should be formed correctly.
Any suggestions? I'm a TDD newbie and really trying to learn here. :)
Edit:
It seems the culprit was this. My Test was using: Func pageUrl = i => "Page" + 1;
instead of
Func pageUrl = i => "Page" + i;
But now there's another error. :(
It seems something is wrong when calculating the amount of pages in the PagingInfo class:
public class PagingInfo
{
public int TotalItems { get; set; }
public int ItemsPerPage { get; set; }
public int CurrentPage { get; set; }
public int TotalPages
{
get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); }
}
}
It seems the error stems on the fact that this is returning 2 pages, instead of 3.
Is there something wrong in this calculation?
(Replying to the new question posed in your edit.) Your loop in PageLinks()
is starting with i = 1
and having i < pagingInfo.TotalPages
as condition - a classical off-by-one error. :-)
Is there something wrong in this calculation?
Good question. As an exercise in proper Test-Driven Design, try creating a unit test that isolates this specific calculation. Something like this:
Assert.AreEqual(3, new PagingInfo {TotalItems = 4, ItemsPerPage = 9}.TotalPages);
If these unit tests show that the function is calculating your input correctly, then you know that the consuming class must be providing the wrong inputs.
The real issue here is probably the one that Aasmund found, but I hope this answer gives you an idea about how to improve your unit testing to hone in on the real source of errors.
Is there something wrong in this calculation?
public int TotalPages
{
get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); }
}
Yes, you are playing fast and loose with the types and operations involved. Without knowing operator precedence, you don't know if the decimal convert is applied before the divide, and therefore don't know if the divide is a decimal divide or an int divide.
Use multiple statements and be clear with the types. Read this post.
I will consider the downvote as a prompt for more help. Consider this: the inputs are all integers. Can the problem be resolved in the domain of integers? Is it necessary to involve decimals at all?
public int GetTotalPages()
{
int fullPages = TotalItems / ItemsPerPage;
bool partialPage = TotalItems % ItemsPerPage != 0;
int result = fullPages + (partialPage ? 1 : 0);
return result;
}
精彩评论