Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting DRY with Rhino Mocks

I am looking for ways of making the following more concise.

public class MyTests
{
    IPresenter presenter;

    [SetUp]
    public void SetUp()
    {
        presenter = MockRepository.GenerateStub<IPresenter>();
    }

    ...
}

In particular specifying the type again when creating the mock seems redundant. For example I can write it this way and use reflection to get the type and create the stub automatically:

public class MyTests
{
    IPresenter presenter;

    [SetUp]
    public void SetUp()
    {
        Stub(x => x.presenter);
    }

    void Stub(Expression<Func<MyTests, object>> expression)
    {
        ...
    }
}

This would work but the compiler can no longer detect that presenter is assigned and starts issuing warnings. This also makes ReSharper very unhappy.

Can anyone suggest a better approach?

like image 814
Generic Error Avatar asked Jan 28 '10 22:01

Generic Error


2 Answers

This may be controversial, but I favour readability, rather than DRY-ness* in unit tests.

In other words, set up methods are none existant in my unit tests. They are only used for integration tests. I believe XUnit.NET takes this stance too.

So to answer your question, I really would not worry about setting up mock presenters in each of your tests that require one. Some tests may not need a mock presenter, therefore having one set up before the test is run is not necessary.

**Naturally, my unit tests span say ten lines average, if this increases or the scope of setting up the test (following AAA - Arrange, Act Assert) is large, only then will I remove the duplication and create helper methods. To clear this point up, for cleaner tests, you can create a base test class that contains the helper methods and other set up code.*

like image 61
Finglas Avatar answered Oct 04 '22 12:10

Finglas


Yes, don't use [Setup] and member variables at all, write Fixture Objects with creation methods instead.

The Fixture Object would simply hold the appropriate mock and other parts of the Fixture.

I personally use AutoFixture as a Fixture Object, and have it set up as an Auto-Mocking Container to boot, so I don't have to write any mock code unless I need to explicitly define some behavior.

Here's a recent sample unit test:

[TestMethod]
public void DeleteProductWillDeleteProductFromRepository()
{
    // Fixture setup
    var fixture = new ServiceFixture();
    var id = fixture.CreateAnonymous<int>();
    var repMock = fixture.FreezeMoq<ProductRepository>();

    var sut = fixture.CreateAnonymous<ProductManagementService>();
    // Exercise system
    sut.DeleteProduct(id);
    // Verify outcome
    repMock.Verify(r => r.DeleteProduct(id));
    // Teardown
}

In this case, repMock is created by Moq, but I could have set it up to use Rhino Mocks instead.

like image 22
Mark Seemann Avatar answered Oct 04 '22 10:10

Mark Seemann