Last active
February 11, 2016 19:12
-
-
Save darrencauthon/fd08e45f0db38c5edf16 to your computer and use it in GitHub Desktop.
Testing samples, strict or loose
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using AutoMoq.Helpers; | |
using Moq; | |
using NUnit.Framework; | |
namespace JamesDemo | |
{ | |
public class Presenter | |
{ | |
private readonly IRepository repository; | |
private readonly IWeather weather; | |
private readonly IView view; | |
public Presenter(IView view, IRepository repository, IWeather weather) | |
{ | |
this.view = view; | |
this.repository = repository; | |
this.weather = weather; | |
} | |
public void Present() | |
{ | |
if (weather.Today() != "Cloudy") view.DoStuff(); | |
repository.DoStuff(); | |
} | |
} | |
public interface IView | |
{ | |
void DoStuff(); | |
} | |
public interface IRepository | |
{ | |
void DoStuff(); | |
} | |
public interface IWeather | |
{ | |
string Today(); | |
} | |
[TestFixture] | |
public class JamesTests | |
{ | |
private Mock<IView> mockView; | |
private Mock<IRepository> mockRepo; | |
private Presenter presenter; | |
private Mock<IWeather> weather; | |
[Test] | |
public void VerifyTheRepoDoesStuff() | |
{ | |
mockView = new Mock<IView>(MockBehavior.Loose); | |
mockRepo = new Mock<IRepository>(MockBehavior.Strict); | |
weather = new Mock<IWeather>(MockBehavior.Strict); | |
presenter = new Presenter(mockView.Object, mockRepo.Object, weather.Object); | |
//do setups on repo that i specifically care about. | |
weather.Setup(x => x.Today()).Returns("Sunny"); | |
mockRepo.Setup(x => x.DoStuff()).Verifiable(); | |
presenter.Present(); | |
mockRepo.VerifyAll(); | |
} | |
[Test] | |
public void VerifyTheViewDoesStuff() | |
{ | |
mockView = new Mock<IView>(MockBehavior.Strict); | |
mockRepo = new Mock<IRepository>(MockBehavior.Loose); | |
weather = new Mock<IWeather>(MockBehavior.Strict); | |
presenter = new Presenter(mockView.Object, mockRepo.Object, weather.Object); | |
//do setups on view that i specifically care about. | |
weather.Setup(x => x.Today()).Returns("Sunny"); | |
mockView.Setup(x => x.DoStuff()).Verifiable(); | |
presenter.Present(); | |
mockView.VerifyAll(); | |
} | |
} | |
[TestFixture] | |
public class AutoMoqTests : AutoMoqTestFixture<Presenter> | |
{ | |
[SetUp] | |
public void Setup() | |
{ | |
ResetSubject(); // probably not necessary, but just | |
// in case -- it resets automoq | |
// do your common setup up here | |
Mocked<IWeather>().Setup(x => x.Today()).Returns("Sunny"); | |
} | |
[Test] | |
public void VerifyThatTheRepoDoesStuff() | |
{ | |
Mocked<IRepository>().Setup(x => x.DoStuff()).Verifiable(); | |
Subject.Present(); | |
Mocked<IRepository>().VerifyAll(); | |
} | |
[Test] | |
public void VerifyThatTheViewDoesStuff() | |
{ | |
Mocked<IView>().Setup(x => x.DoStuff()).Verifiable(); | |
Subject.Present(); | |
Mocked<IView>().VerifyAll(); | |
} | |
[Test] | |
public void When_the_weather_is_cloudy_then_the_view_should_not_do_something() | |
{ | |
Mocked<IWeather>().Setup(x => x.Today()).Returns("Cloudy"); | |
Mocked<IView>().Setup(x => x.DoStuff()).Throws(new Exception("Should not have been called")); | |
Subject.Present(); | |
// the test would have thrown if the error occurred | |
} | |
[Test] | |
public void When_the_weather_is_cloudy_then_the_repo_should_still_do_something() | |
{ | |
Mocked<IWeather>().Setup(x => x.Today()).Returns("Cloudy"); | |
Mocked<IRepository>().Setup(x => x.DoStuff()).Verifiable(); | |
Subject.Present(); | |
Mocked<IRepository>().Verify(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Both of these test fixtures test the same code.
In this particular case, there is no functional difference between
Strict
andLoose
. If you callVerifyAll
then your "loose" mock is actually a "strict" mock by the fact that an assertion is being made against the mock. Or simply: Everything assigned as Verifiable is strict.I just don't find any practical use for the
Strict
behavior. I usually configure my test to run through the "happy" path in the setup method marked with[SetUp]
, so I can call the method I'm testing in the test without any additional setup. Then whatever I want to assert -- whether it be through a mock verification or testing the result -- is the only thing in my test method.I had one example where I thought a strict mock would help last week, but it was a very rare, complicated method that did not follow SRP and was written long before I wrote the first test for it. I wanted to verify that one method on one dependency was called only in one circumstance. "Loose" doesn't care if you call it, but I wanted the mock to care. Rather than going strict, I went the other direction with a fake:
I'd say that exception is just as helpful as any strict mock would be. 😄