Getting DRY with Rhino Mocks

I am looking for ways to make 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 layout seems redundant. For example, I can write it this way and use reflection to get the type and create a stub automatically:

 public class MyTests { IPresenter presenter; [SetUp] public void SetUp() { Stub(x => x.presenter); } void Stub(Expression<Func<MyTests, object>> expression) { ... } } 

This will work, but the compiler will no longer be able to determine if a leader has been assigned and will start to issue warnings. It also makes ReSharper very unhappy.

Can anyone suggest a better approach?

+6
c # unit-testing dry nunit rhino-mocks
source share
4 answers

This may be controversial, but I prefer readability over DRY-ness * in unit tests.

In other words, tuning methods do not exist in my unit tests. They are used only for integration tests. I believe that XUnit.NET also takes this position.

So, to answer your question, I really would not have to worry about customizing the layout of the presenters in each of your tests that require one. Some tests may not require a mock presenter, so having one setting before running the test is not required.

** Naturally, my unit tests cover about ten lines, if this increases or the test setup volume (after AAA - Arrange, Ass Assert) is large, only then I will remove duplication and create auxiliary methods, To clear this point, for cleaner tests you can create a base test class that contains helper methods and other customized code. *

+5
source share

Yes, do not use [Setup] and member variables at all, write Fixture Objects instead of creation methods.

The Fixture object simply holds the corresponding layouts and other parts of the Fixture.

I personally use AutoFixture as a Fixture object and set it up as an Auto-Mocking Container to load, so I don’t need to write any mock code if I don’t need to explicitly define any behavior.

Here is a recent unit test sample:

 [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 customize it instead of using Rhino Mocks.

+3
source share

Michael Perce has an outstanding perspective on this (see his presentation http://www.ndc2010.no/index.aspx?id=361621 ). Create Builders and use this in tests instead of all kinds of customization.

Like:

  //The Class to Test public class ObjectY { public string DoThis(IObjectX objectX) { return objectX.id + objectX.name; } } [Test] //The test public void CreaeteTestData() { //Almost prosa style creation of test data var testData = new ObjectXBuilder().WithId(123).WithName("ABC").Build(); Assert.That(new ObjectY().DoThis(testData), Is.EqualTo("123ABC")); } //The Builder class - Provides easy creation testdata. internal class ObjectXBuilder { private MockRepository _mockRepository; private IObjectX _objectX; public ObjectXBuilder() { _mockRepository = new MockRepository(); _objectX = _mockRepository.Stub<IObjectX>(); } public ObjectXBuilder WithName(string name) { _objectX.name = name; return this; } public ObjectXBuilder WithId(long id) { _objectX.id = id; return this; } public IObjectX Build() { _mockRepository.ReplayAll(); return _objectX; } } 
+1
source share

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

In any case, if my tests are good and small, I try to initialize all the layouts inside each test case. Thus, you can look at each test in isolation from other tests and immediately see what happens there. If they become long, although I just use the unpleasant method that you inserted at the beginning of your question.

0
source share

All Articles