Reputation: 1611
I've been mocking using moq for a while and always find myself doing things like this:
Assume the behavior I want to test is that classUnderTest.DoSomething() calls l.Fatal("My test message") once.
//arrange
mockLogger.Setup(l => l.Fatal("My test message"));
//act
classUnderTest.DoSomething()
//assert
mockLogger.Verify(l => l.Fatal("My test message"), Times.Once());
I feel like the verify call is always a repetition of the setup except with the Times parameter. I would really like to know what others are doing even with different mocking frameworks. Is there a better way to do this?
Upvotes: 4
Views: 654
Reputation: 2469
You only need to do the setup on the Mock object if you actually need to control the behaviour of what it does, such as returning stuff:
_mockRepo.SetUp(m => m.DoStuff()).Returns(someObject);
or throw an exception:
_mockRepo.SetUp(m => m.DoStuff()).Throws(new SomeExceptionType());
I assume, in your example, you're passing the logger mock object into some other object under test, in which case removing the setup call will have no effect, as the equivalent setup will be done just by creating the Mock object.
Edit
public class Dude : IDude
{
private IAirSupport _support;
public Dude(IAirSupport support)
{
_support = support;
}
public void Advance(Place place)
{
if(place.IsUnderAttack)
{
_support.CoveringFire(place);
MoveAndFire(place);
}
}
}
To mock this one:
var support = new Mock<IAirSupport>();
var dude = new Dude(support.Object);
var place = new HotSpot { IsUnderFire = true };
dude.Advance(place);
support.Verify(m => m.CoveringFire(place), Times.Once());
This is all you need - Verify does all the heavy lifting, no reason to call setup.
Upvotes: 4
Reputation: 13079
Try rearranging your test like this
//arrange
var mockLogger = new Mock<ILogger>();
var classUnderTest = new Foo(mockLogger.Object);
//act
classUnderTest.DoSomething();
//assert
mockLogger.Verify(l => l.Fatal("My test message"), Times.Once());
This way you don't need the double assert nor the duplicated test data. Basically I would suggest to either go for strict mocking with setting up expected calls in advance using Setup
or use the Verify
syntax. I personally like the verify syntax more since what is beeing asserted is very clear.
Upvotes: 1
Reputation: 6588
I agree with your sentiment that it feels repetitive. However, in this particular instance I don't think you need to call Setup()
as you are not returning anything. I normally only call Setup()
if I need to assert something based on the object returned.
Recently I have started using AutoMocking via structure map which prompted me to write a few shortcut/utility methods on the base class to access the auto generated mocks. I was then able to write a shortcut to call Verify()
also. It might save you a keystroke or two... http://evolutionarydeveloper.blogspot.co.uk/2012/10/automock-with-structuremap-and-moq.html
Upvotes: 2
Reputation: 3844
I aggree that a lot of testing feels repetitive, but I don't see how things can be done much easier than you describe.
All unit tests follow the pattern: setup-execute-assert (at least the good ones). This is exactly what your example does elegantly. You can argue how you set up, and how you assert, but you have done each in one line of code, and finding a method to top that is hard.
Upvotes: 0