Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <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>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COThanks for deciphering this one! Mixed emotions when the answer turns out to be a bug in the library I'm using… I stumbled onto this by accident because some of my XXXBuilder classes were sealed, some not. Discovered the argument about whether to seal classes in absence of a good reason to not seal, or do the opposite. Seems like sealing classes can cause unit testing friction - care to share an opinion on the matter?
      singulars
    2. COThe notion that sealed classes hurt testability originates (I think) from Java, where all members are virtual by default. In C# this isn't the case, so the question becomes less important. In any case, if you *favour composition over inheritance* it hardly matters. FWIW, F# constructs such as records compile to sealed classes, but F# code can be very testable none the less. Ultimately, if you follow TDD, you'll have testable code :)
      singulars
    3. COI should clarify that sealed classes seem to hurt testability when the mocking framework in use is unable to mock sealed classes, yet is being asked to do so. Then one is left choosing between implementing a certain 'accessibility' feature, [as prominent people assert](http://stackoverflow.com/a/2165287/533958), by making the class non-sealed simply because the *mocking tool* needs it, and keeping the class sealed so one needn't design for inheritance. Point taken, however, regarding TDD development.
      singulars
 

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