Reputation: 43
I am trying to test a method called Login that, when the user and password parameters are correct, sets the value of two session variables and three cookies and finally returns true.
I've been reading several posts about unit testing, but somehow that didn't make my case fully clear to me. I know that there should be just a single assert per unit test, although you can use more than one as long as you test a single "logical concept".
Login method is correct only if it sets correctly every session variable and cookie and returns the expected value, so I'm not sure if it would be ok to check all these values at once (that would lead me to use six asserts in the unit test, a bit dirty I think) or if I should check the value of each session variable and cookie separately in different tests.
[TestMethod()]
public void SuccessfulLoginTest()
{
// Arrange.
String username = "foo";
String password = "correct password";
Boolean remember = true;
// Act.
Boolean actual = Login(username, password, remember);
// Assert.
Assert.IsTrue(actual);
Assert.AreEqual("foo", HttpContext.Current.Session["Username"]);
Assert.AreEqual(1, HttpContext.Current.Session["Group"]);
Assert.AreEqual("foo", HttpContext.Current.Response.Cookies["Username"].Value);
Assert.AreEqual("en", HttpContext.Current.Response.Cookies["Lang1"].Value);
Assert.AreEqual("es", HttpContext.Current.Response.Cookies["Lang2"].Value);
}
Upvotes: 4
Views: 627
Reputation: 35891
You've already noticed correctly, that the one assert rule concerns conceptual assertions, not bare calls to the Assert
methods. A nice and common trick that reduces confusion when one logical assert is composed of many assertions and also makes the test more readable is wrapping the asserts in an utility method. In your case it could look similar to this:
void AssertSessionIsValid(string username, int group, ...)
{
Assert.AreEqual(username, HttpContext.Current.Session["Username"]);
Assert.AreEqual(group, HttpContext.Current.Session["Group"]);
...
}
There are many frameworks that help in increasing readability of your tests, like Shouldly.
Upvotes: 3
Reputation: 3931
I'd suggest to assert everything you care about being 'working' and no more than that. Too few asserts and your test will ignore clearly broken functionality; too many and your test will be brittle and break unnecessarily when some irrelevant detail changes.
Upvotes: 1
Reputation: 18155
Looks fine to me too. I'm not sure where you got the notion that there should only be one Assert per unit test. That sounds like an "ivory tower" rule that is just plain silly IMO. If your method sets a bunch of variables given a particular input then you should check all those variables given that input. Writing six different unit tests (and associated setup code) seems incredibly inefficient.
But then I tend to lean towards pragmatism over academic "correctness" when it comes to writing software.
Upvotes: 3
Reputation: 405
Have your conditions matched in a boolean variable and if all are fulfilled, then the boolean variable should return true.
Asset this boolean variable
bool AreAllConditionsFulfilled = condition1 && condtionCheckingSessionVariablesOne && conditionCheckingSessionVariablesTwo
Also I would suggest have individual test cases testing each of the Session Variables and assert if they are correct.
[Test]
public void TestUserNameSessionVariable()
{
//Login Code
Assert.AreEqual("foo", HttpContext.Current.Session["Username"]);
}
Upvotes: -1