Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you look at the stack trace, you'll notice that the exception happens deep within Moq. AutoFixture is an opinionated library, and one of the opinions it holds is that <strong>nulls are invalid return values</strong>. For that reason, <em>AutoMoqCustomization</em> configures all Mock instances like this:</p> <pre><code>mock.DefaultValue = DefaultValue.Mock; </code></pre> <p>(among other things). Thus, you can reproduce the failing test entirely without AutoFixture:</p> <pre><code>[Fact] public void ReproWithoutAutoFixture() { var factory = new Mock&lt;IBuilderFactory&gt;(); factory.DefaultValue = DefaultValue.Mock; var sut = new BuilderService(factory.Object); sut.Create(); // EXCEPTION THROWN!! factory.Verify(f =&gt; f.Create(), Times.Once()); } </code></pre> <p>The strange thing is that it still seems to work with sealed classes. This is, however, not quite true, but rather originates in the OP tests being <a href="http://xunitpatterns.com/false%20negative.html">False Negatives</a>.</p> <p>Consider this <a href="http://en.wikipedia.org/wiki/Characterization_test">Characterization Test</a> of Moq:</p> <pre><code>[Fact] public void MoqCharacterizationForUnsealedClass() { var factory = new Mock&lt;IBuilderFactory&gt;(); factory.DefaultValue = DefaultValue.Mock; Assert.Throws&lt;ArgumentException&gt;(() =&gt; factory.Object.Create()); } </code></pre> <p>Moq <em>correctly</em> throws an exception because it's been asked to create an instance of CubeBuilder, and it doesn't know how to do that, because CubeBuilder has no default constructor, and no <code>Setup</code> tells it how to deal with calls to <code>Create</code>.</p> <p>(As an aside, the irony here is that AutoFixture would be perfectly able to create an instance of CubeBuilder, but there's no extensibility point in Moq that enables AutoFixture to go in and take over Moq's default object instance creation behaviour.)</p> <p>Now consider this Characterization test when a return type is sealed:</p> <pre><code>[Fact] public void MoqCharacterizationForSealedClass() { var factory = new Mock&lt;IBuilderFactoryForSealedBuilder&gt;(); factory.DefaultValue = DefaultValue.Mock; var actual = factory.Object.Create(); Assert.Null(actual); } </code></pre> <p>It turns out that in this case, despite having been implicitly told not to return <code>null</code>, Moq does so anyway.</p> <p>My theory is that what's really going on is that in <em>MoqCharacterizationForUnsealedClass</em> above, what <code>factory.DefaultValue = DefaultValue.Mock;</code> really means is that Moq creates a <em>mock</em> of CubeBuilder - in other words, it dynamically emits a class that <em>derives</em> from CubeBuilder. However, when asked to create a <em>mock</em> of SealedCubeBuilder, it can't, because it can't create a class derived from a sealed class.</p> <p>Instead of throwing an exception, it returns <code>null</code>. This is inconsistent behaviour, and <a href="https://github.com/Moq/moq/issues/3">I've reported this as a bug in Moq</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload