views:

124

answers:

3

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?

+1  A: 

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.

Mark Seemann
with no [Setup] or [Teardown], xUnit ftw!
mxmissile
You're trading a member variable + initializer for extra set up in each method which is going to add up with more than a few tests.Auto mocking is something I should look at though, thanks.
Generic Error
+4  A: 

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.

Finglas
I mostly agree with this (hence the +1), but would also like to suggest you can create an inner class for tests with mocks if you're going to have a lot of test cases using them.
jonnii
@jonni - You beat me to my edit. But I agree.
Finglas
@finglas It's a circle of agreement. Lets pat each other on the back ;)
jonnii
DRY code tends to contribute greatly to readability IMHO. I am looking at ways of cutting down the noise so that the important parts can be see.
Generic Error
@Generic Error: If other developers are going to work on this code base, Your first example is far more easier to grok for a new person than the second version using lambda expressions. To quote Jon from his book, 'Simple is almost always better than clever'
Gishu
@Generic - I'd disagree. For code yes, for test code though not so much. Having to scroll up the screen for to see how a test is set up is a pain for example. This is especially true when test fail, and someone needs to come along after and fix them. I (and others) would much prefer an isolated test that reads easy, over one that uses more complex language features to reduce duplication.
Finglas
Do you not find that repeating the setup makes for a lot of broken tests when it comes to refactoring?
Generic Error
It depends on how complex the setup is. In your example, setting up a simple mock object is nothing. If however you had several and had to set up some values or states with them, removing the setup could be benefical. Thai is, as long as more than one test required the same setup.
Finglas
A: 

Its a general pain with C#, that it doesn't infer the type from the method result (unlike Java), and it is painful in many situations (just to give another example, where you want to implement a deserialising method). Personally I don't like using the var keyword, because I want to see exactly what is the type of my objects, I would prefer to skip the type name in the template.

Anyway, if my tests are nice and small I tend to initialise all the mocks inside each test case. This way you can look at every tests in separation from the other tests and immediately see what is happening there. If they get longish though I just use the nasty way you pasted at the beginning of your question.

Grzenio