public
Last active — forked from amirrajan/gist:3845281

Fun with tests.

  • Download Gist
gistfile1.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
namespace Accounts
{
namespace NewAccounts
{
public class When_creating_a_new_account {
Account account = new Account();
public void Does_not_have_any_subscriptions() {
account.Subscriptions.Count.ShouldEqual(0);
}
public void Does_not_have_any_sites() {
account.Subscriptions.Count.ShouldEqual(0);
}
public void Generates_a_new_api_key() {
account.ApiKeys.First().ShouldNotBeEmpty();
}
}
}
 
namespace adding_a_site
{
/* This is a bad test. It's coupled to the implementation of the object mother's factory method */
public class When_the_site_already_exists
{
public void ThrowsException() {
Account account = ObjectMother.GetAccountWithSite();
typeof(InvalidOperationException).ShouldBeThrownBy(() => account.AddSite("sites/1"));
}
}
 
/* Collapsed before/act etc. It added no value. */
public class When_no_subscriptions_exist {
 
public void Should_not_add_the_site() {
Account account = new Account();
account.AddSite("sites/1");
account.Sites.Count.ShouldEqual(0);
}
}
/* see above. there's no need to split out AAA */
public class When_no_available_subscriptions_exist {
 
public void Should_not_add_the_site() {
Account account = GetAccountWithSite();
account.AddSite("sites/2");
account.Sites.Count.ShouldEqual(1);
}
}
public class When_available_subscriptions_exist {
 
public void Should_add_the_site() {
Account account = new Account();
account.AddSubscription(ObjectMother.GetValidSubscription());
account.AddSite("sites/1");
account.Sites.Count.ShouldEqual(1);
}
}
/* These previous tests should really be consolidated into one test class
Separating out into indvidual classes doesn't add any value.
*/
}
 
/* Also don't like this test. Change GetAccountWithSite with a different site, BOOM */
public class validating_sites
{
Account account = ObjectMother.GetAccountWithSite();
 
public void When_the_specified_site_is_mapped_to_the_account_should_be_valid {
account.ValidateSite("sites/1").ShouldBeTrue();
}
 
public void When_the_specified_site_is_not_mapped_to_the_account() {
account.ValidateSite("sites/2").ShouldBeFalse();
}
}
 
/* Common act, also a bad idea. It adds nothing but needless indirection */
public class validating_subscriptions
{
public void When_the_account_has_a_valid_subscription_should_report_as_valid {
Account account = new Account();
account.AddSubscription(GetValidSubscription());
 
account.HasValidSubscription().ShouldBeTrue();
}
 
public void When_the_account_has_no_valid_subscriptions_should_report_as_invalid {
Account account = new Account();
account.AddSite("sites/1");
var subscription = new Subscription(
"products/1",
"Fabrik Subscription",
69M,
DateTime.UtcNow.AddMonths(-13), // expired by one month
new SubscriptionDuration(1, SubscriptionPeriod.Yearly));
 
account.AddSubscription(subscription);
 
account.HasValidSubscription().ShouldBeFalse();
}
}
 
public static class ObjectMother {
public Subscription GetValidSubscription()
{
return new Subscription(
"products/1",
"Fabrik Subscription",
69M,
DateTime.UtcNow,
new SubscriptionDuration(1, SubscriptionPeriod.Yearly)
);
}
 
public Account GetAccountWithSite()
{
var account = new Account();
account.AddSubscription(GetValidSubscription());
account.AddSite("sites/1");
return account;
}
}
}

Whew! Got rid of all the common arrange/acts as these tests really didn't need them. Only one test might need test class per fixture pattern (the first). The rest really needed to have their own isolated fixtures.

I'm not a huge fan of ObjectMother, I'd rather use AutoFixture in this case, or Fubu's way of object builder specifications for complex domains.

One other thing - when a test fails here, I can use standard IDE tools to navigate to type/member. With strings as keys representing test methods, I'm relegated to grep tools (not in my IDE) or "Find in Files" (much, much clunkier).

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.