Skip to content

Instantly share code, notes, and snippets.

@olsonjeffery
Created November 30, 2010 18:52
Show Gist options
  • Save olsonjeffery/722166 to your computer and use it in GitHub Desktop.
Save olsonjeffery/722166 to your computer and use it in GitHub Desktop.
An idea of what a useful API for using fluent fixtures might look like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Client.Framework;
using NHibernate;
namespace Example.Specs.Creators
{
// Creator<T> provides an framework for defining streamlined, *test-only* factories for domain entities..
// it mostly provides needed infrastructure that a test harness can hook into to make it possible to
// create and persist Nhib entities in a test environment.
public class Creator<T>
{
// the only thing worth knowing about ISessionProvider is that it wraps an NHib ISession
ISessionProvider _sessionProvider;
// This represents the various databases that the client has
DatabaseName _db;
// we keep an instance of the FluentFixtures ourselves as a member here so that a Creator
// has access to New, the same as the test code shown in fluent_fixtures_example.cs
FluentFixtures _fixtures;
public FluentFixtures New { get { return _fixtures; } }
public Creator(ISessionProvider sessionProvider, DatabaseName db,FluentFixtures fixtures)
{
_sessionProvider = sessionProvider;
_db = db;
_fixtures = fixtures;
}
public void Flush()
{
Session.Flush();
}
public void Evict()
{
Session.Evict(Creation);
}
public void Save()
{
Session.Save(Creation);
// we're flushing left-and-right for convenience.. not performant at all and
// obviously not aprop. for production use.
Flush();
}
public K SimpleChange<K>(Action<T> input) where K: Creator<T>
{
input(Creation);
Save();
return (K)this;
}
public T Creation { get; set; }
public ISession Session { get { return _sessionProvider.CurrentSessionOn(_db); } }
public static implicit operator T (Creator<T> input)
{
return input.Creation;
}
}
}
// This is an example of some fixture code I've written recently for my current client (posted with their permission).
// The domain concerned here is a basic scheduling system for the client's provided continuing education offerings for
// customers.
// Each one of the Nouns that comes after "New." is an example of a "Creator" for a given, existent
// domain entity. The Creators are usually named, by convention, along the lines of: EntityNameCreator.
// That all inherit from Creator<T>, where T is the domain entity that they represent.
//
// The "New" member, itself, is an instance of a FluentFixture type, that holds methods (one for each noun) that give
// access to the creators. Creator<T> has an implicit cast impl to converting a Creator to its domain entity representation
// as needed.
var class1 = New.Class()
.Named("Title & Escrow For Dummies")
.WithCourseNumber("2345")
.WithHours(3)
.IsOwnedByTheCompany()
.DescribedAs("Something interesting.")
.ExpiresOn(DateTime.Now.AddMonths(1));
var class2 = New.Class()
.Named("Fooing the Bar")
.WithCourseNumber("BlahBlah10")
.WithHours(5)
.IsNotOwnedByTheCompany()
.DescribedAs("fourty two.")
.ExpiresOn(DateTime.Now.AddMonths(3));
var venue1 = New.Venue()
.LocatedAt("123 1st St", "Seattle", "WA", "98001")
.DescribedAs("A very nice place.")
.DrivingDirections("Get there.")
.WithMaxAttendenceOf(5)
.InRoom("101")
.Named("Nice classroom");
var schedClass = New.ScheduledClassFor(class1, venue1)
.ThatCosts(100.0m)
.On(DateTime.Now.AddDays(7))
.StartTime(new DateTime(2000, 1, 1, 9, 0, 0));
var fooEmpId = new Guid("0"); // user id for foo
var instructor = New.Instructor()
.WhoIs(fooEmpId)
.WhoIsTeaching(schedClass, false);
var anotherInstructor = New.Instructor()
.WithContactInfo("Joe", "Snuffy", "joe@snuffy.test", "(206) 123-4567")
.WhoIsTeaching(schedClass, true);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Client.Framework;
namespace Example.Specs.Creators
{
// And finally an example of the FluentFixtures class, instances of which appear in Creator.cs and
// fluent_fixtures_example.cs as the "New" member.
public class FluentFixtures
{
ISessionProvider _sessionProvider;
public FluentFixtures(ISessionProvider sessionProvider)
{
_sessionProvider = sessionProvider;
}
public ISessionProvider SessionProvider { get { return _sessionProvider; } }
public ClassInformationCreator Class()
{
return new ClassInformationCreator(SessionProvider, this);
}
public ScheduledClassCreator ScheduledClassFor(ClassInformation ci, Venue v)
{
return new ScheduledClassCreator(SessionProvider, this, ci, v);
}
public VenueCreator Venue()
{
return new VenueCreator(SessionProvider, this);
}
public InstructorCreator Instructor()
{
return new InstructorCreator(SessionProvider, this);
}
public T From<T, TType>() where T: Creator<TType>, new()
{
var foo = new T();
foo.Initialize(SessionProvider, this);
return foo;
}
public string RandomName { get { return Guid.NewGuid().ToString(); } }
public string ShortName { get { return RandomName.Substring(0, 4); } }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Client.Framework;
namespace Example.Specs.Creators
{
// An example of a Creator<T> implementation for the domain concept of an
// Instructor as shown in fluent_fixtures.cs
public class InstructorCreator : Creator<Instructor>
{
IEmployeeQueryService _eqs;
public InstructorCreator(ISessionProvider sp, FluentFixtures fixtures)
: base(sp, DatabaseName.Foo, fixtures)
{
Creation = new Instructor();
_eqs = new EmployeeQueryService(sp);
Save();
}
public InstructorCreator WhoIs(Guid empId)
{
Creation.EmpId = empId;
var emp = _eqs.EmployeeBy(empId);
Creation.FirstName = emp.FirstName;
Creation.LastName = emp.LastName;
Creation.Email = emp.Email;
Creation.ContactPhone = emp.Phone;
Save();
return this;
}
public InstructorCreator WithContactInfo(string firstName, string lastName, string email, string phone)
{
Creation.FirstName = firstName;
Creation.LastName = lastName;
Creation.Email = email;
Creation.ContactPhone = phone;
Save();
return this;
}
public InstructorCreator WhoIsTeaching(ScheduledClass sc, bool primaryInstructor)
{
var rel = new InstructorForScheduledClass();
rel.Instructor = this; // an example of the implicit casting that gives some flexibility to a Creator
rel.ScheduledClass = sc;
rel.PrimaryInstructor = primaryInstructor;
Session.Save(rel);
Save();
return this;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment