Skip to content

Instantly share code, notes, and snippets.

@darrencauthon
Last active February 11, 2016 19:12
Show Gist options
  • Save darrencauthon/fd08e45f0db38c5edf16 to your computer and use it in GitHub Desktop.
Save darrencauthon/fd08e45f0db38c5edf16 to your computer and use it in GitHub Desktop.
Testing samples, strict or loose
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();
}
}
}
@darrencauthon
Copy link
Author

Both of these test fixtures test the same code.

In this particular case, there is no functional difference between Strict and Loose. If you call VerifyAll 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:

Mocked<IView>()
    .Setup(x => x.DoStuff())
    .Callback(() => throw new Exception("Should not have been called!"));

I'd say that exception is just as helpful as any strict mock would be. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment