ahsteele
ahsteele

Reputation: 26514

Seeding repository Rhino Mocks

I am embarking upon my first journey of test driven development in C#. To get started I'm using MSTest and Rhino.Mocks. I am attempting to write my first unit tests against my ICustomerRepository. It seems tedious to new up a Customer for each test method. In ruby-on-rails I'd create a seed file and load the customer for each test. It seems logical that I could put this boiler plate Customer into a property of the test class but then I would run the risk of it being modified. What are my options for simplifying this code?

[TestMethod]
public class CustomerTests : TestClassBase
{
    [TestMethod]
    public void CanGetCustomerById()
    {
        // arrange
        var customer = new Customer()
        {
            CustId = 5,
            DifId = "55",
            CustLookupName = "The Dude",
            LoginList = new[] {
                new Login { LoginCustId = 5, LoginName = "tdude" } }
        };

        var repository = Stub<ICustomerRepository>();

        // act
        repository.Stub(rep => rep.GetById(5)).Return(customer);

        // assert
        Assert.AreEqual(customer, repository.GetById(5));
    }

    [TestMethod]
    public void CanGetCustomerByDifId()
    {
        // arrange
        var customer = new Customer()
        {
            CustId = 5,
            DifId = "55",
            CustLookupName = "The Dude",
            LoginList = new[] {
                new Login { LoginCustId = 5, LoginName = "tdude" } }
        };

        var repository = Stub<ICustomerRepository>();

        // act
        repository.Stub(rep => rep.GetCustomerByDifID("55")).Return(customer);

        // assert
        Assert.AreEqual(customer, repository.GetCustomerByDifID("55"));
    }

    [TestMethod]
    public void CanGetCustomerByLogin()
    {
        // arrange
        var customer = new Customer()
        {
            CustId = 5,
            DifId = "55",
            CustLookupName = "The Dude",
            LoginList = new[] {
                new Login { LoginCustId = 5, LoginName = "tdude" } }
        };

        var repository = Stub<ICustomerRepository>();

        // act
        repository.Stub(rep =>
            rep.GetCustomerByLogin("tdude")).Return(customer);

        // assert
        Assert.AreEqual(customer, repository.GetCustomerByLogin("tdude"));
    }
}

Test Base Class

public class TestClassBase
{
    protected T Stub<T>() where T : class
    {
        return MockRepository.GenerateStub<T>();
    }
}

ICustomerRepository and IRepository

public interface ICustomerRepository : IRepository<Customer>
{
    IList<Customer> FindCustomers(string q);
    Customer GetCustomerByDifID(string difId);
    Customer GetCustomerByLogin(string loginName);
}

public interface IRepository<T>
{
    void Save(T entity);
    void Save(List<T> entity);
    bool Save(T entity, out string message);
    void Delete(T entity);
    T GetById(int id);
    ICollection<T> FindAll();
}

Upvotes: 2

Views: 984

Answers (3)

PatrickSteele
PatrickSteele

Reputation: 14687

Your unit tests don't have any real value because they're just testing Rhino.Mocks.

What you want to do is use Rhino.Mocks to create an ICustomerRepository stub for other components/services that need an ICustomerRepository. This way, instead of using a CustomerRepository that talks to a database or some flat file, you'll use the stubbed ICustomerRepository and Rhino.Mocks will let you set up pre-defined responses to certain methods, thus allowing you to test your services in isolation.

Upvotes: 3

ckramer
ckramer

Reputation: 9443

I would extract the code to create the customer into a method. You can call that from your test methods, and if you name it something like SetUpCustomerForRepository then it will provide some documentation about what you are doing.

Here is an example based on your sample:

 private Customer SetUpCustomerForRepository()
 {
    return new Customer()
    {
        CustId = 5,
        DifId = "55",
        CustLookupName = "The Dude",
        LoginList = new[] {
            new Login { LoginCustId = 5, LoginName = "tdude" } }
    };
 }

You could also call it from the test set up method, but I actually prefer to do it in the test method so that people looking at the test know what is being set up for the test.

As for your concern about it being modified....if that happens, then your tests will fail, and you'll know about it.

Upvotes: 2

Jeff Sternal
Jeff Sternal

Reputation: 48623

You could immunize yourself against changes to your test customer by modifying your stubs and assertions to use its properties:

[TestMethod]
public void CanGetCustomerByDifId() {

    var customer = this.TestCustomer;

    var repository = Stub<ICustomerRepository>();

    repository.Stub(rep => rep.GetCustomerByDifID(customer.DifID))
              .Return(customer);

    Assert.AreEqual(customer, repository.GetCustomerByDifID(customer.DifID));
}

Upvotes: 2

Related Questions