Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Since you request a way to mock a <code>DataContext</code> I assume that you really want to do some <strong>unit tests and not integration tests</strong>.</p> <p>Well, I will tell you how to accomplish this, but first I would like to encourage you to read the following links, they are all about <strong>writing clean testable code</strong>.</p> <ul> <li><p><a href="http://misko.hevery.com/code-reviewers-guide/" rel="nofollow noreferrer">http://misko.hevery.com/code-reviewers-guide/</a></p></li> <li><p><a href="http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf" rel="nofollow noreferrer">http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf</a></p></li> </ul> <p>And check the links from this response:</p> <ul> <li><a href="https://stackoverflow.com/a/10359288/1268570">https://stackoverflow.com/a/10359288/1268570</a></li> </ul> <p>Watch the clean code talks from Misko Hevery (given to the Google people)</p> <ul> <li><p><a href="http://www.youtube.com/watch?v=wEhu57pih5w&amp;feature=player_embedded" rel="nofollow noreferrer">http://www.youtube.com/watch?v=wEhu57pih5w&amp;feature=player_embedded</a></p></li> <li><p><a href="http://www.youtube.com/watch?v=RlfLCWKxHJ0&amp;feature=player_embedded" rel="nofollow noreferrer">http://www.youtube.com/watch?v=RlfLCWKxHJ0&amp;feature=player_embedded</a></p></li> <li><p><a href="http://www.youtube.com/watch?v=-FRm3VPhseI&amp;feature=player_embedded" rel="nofollow noreferrer">http://www.youtube.com/watch?v=-FRm3VPhseI&amp;feature=player_embedded</a></p></li> <li><p><a href="http://www.youtube.com/watch?v=4F72VULWFvc&amp;feature=player_embedded" rel="nofollow noreferrer">http://www.youtube.com/watch?v=4F72VULWFvc&amp;feature=player_embedded</a></p></li> </ul> <p>One thing that I used to repeat to myself and to my fellows at work, is that <strong>anyone can write a unit test, because they are silly easy to write</strong>. So a simple test is essentially all about making some comparisons and throw exceptions if the results fails, anyone can do that. Of course, there are hundreds of frameworks to help us write those tests in an <strong>elegant way</strong>. But the real deal, and the real effort shroud be put on <strong>learn how to write clean testable code</strong></p> <p>Even if you hire Misko Hevery to help you write tests, he will have a real hard time writing them if your code is not test-friendly.</p> <p>Now the way to mock a <code>DataContext</code> objects is: do not do it</p> <p>Instead wrap the calls using a custom interface instead:</p> <pre><code>public interface IMyDataContextCalls { void Save(); IEnumerable&lt;Product&gt; GetOrders(); } // this will be your DataContext wrapper // this wll act as your domain repository public class MyDataContextCalls : IMyDataContextCalls { public MyDataContextCalls(DataClasses1DataContext context) { this.Context = context; } public void Save() { this.Context.SubmitChanges(); } public IEnumerable&lt;Product&gt; GetOrders() { // place here your query logic return this.Context.Products.AsEnumerable(); } private DataClasses1DataContext Context { get; set; } } // this will be your domain object // this object will call your repository wrapping the DataContext public class MyCommand { private IMyDataContextCalls myDataContext; public MyCommand(IMyDataContextCalls myDataContext) { this.myDataContext = myDataContext; } public bool myDomainRule = true; // assume this will be the SUT (Subject Under Test) public void Save() { // some business logic // this logic will be tested if (this.myDomainRule == true) { this.myDataContext.Save(); } else { // handle your domain validation errors throw new InvalidOperationException(); } } } [TestClass] public class MyTestClass { [TestMethod] public void MyTestMethod() { // in this test your mission is to test the logic inside the // MyCommand.Save method // create the mock, you could use a framework to auto mock it // or create one manually // manual example: var m = new MyCommand(new MyFakeDataContextFake()); m.Invoking(x =&gt; x.Save()) //add here more asserts, maybe asserting that the internal // state of your domain object was changed // your focus is to test the logic of the domain object .ShouldNotThrow(); //auto mock example: var fix = new Fixture().Customize(new AutoMoqCustomization()); var sut = fix.CreateAnonymous&lt;MyCommand&gt;(); sut.myDomainRule = false; sut.Invoking(x =&gt; x.Save()) .ShouldThrow&lt;InvalidOperationException&gt;(); } public class MyFakeDataContextFake : IMyDataContextCalls { public void Save() { // do nothing, since you do not care in the logic of this method, // remember your goal is to test the domain object logic } public IEnumerable&lt;Product&gt; GetOrders() { // we do not care on this right now because we are testing only the save method throw new NotImplementedException(); } } } </code></pre> <p>Notes:</p> <ul> <li><p>When you declare your <code>IMyDataContextCalls</code> interface you are actually abstracting the use of a <code>DataContext</code>, therefore this interface should contain only POCO objects (most of the time), if you follow this approach your interfaces will be decoupled from any undesired dependency.</p></li> <li><p>In the specific <code>MyDataContextCalls</code> implementation, you are explicitly using a <code>DataClasses1DataContext</code> context, but you are free to change the implementation at any time and that <strong>won't affect your external code</strong>, and that's because you are always working with the <code>IMyDataContextCalls</code> interface instead. So at any time you could change for example this implementation for another one using the wonderful <strong>NHibernate</strong> =) or the poor ef or a mock one</p></li> <li><p>At last, but not least. please double check my code, and you will notice that <strong>there are no <code>new</code> operators in the domain objects</strong>. This is a rule of dumb when writing test friendly code: <em>decouple the responsibility of creating objects outside of your domain objects</em></p></li> </ul> <hr> <p>I personally use three frameworks on every project and on every test I write, I really recommend them:</p> <ul> <li><p><a href="https://github.com/AutoFixture" rel="nofollow noreferrer">AutoFixture</a></p></li> <li><p><a href="https://github.com/Moq/moq4" rel="nofollow noreferrer">Moq</a></p></li> <li><p><a href="http://fluentassertions.com/" rel="nofollow noreferrer">FluentAssertions</a></p></li> </ul> <p>For example, in the code above, I showed you how to write a manual <em>fake</em> for your repository, but that clearly is something we do not want to do in a real project, imagine the number of objects you would have to code in order to write your tests.</p> <p>Instead use the power of AutoFixture combined with Moq:</p> <p>This line: <code>var m = new MyCommand(new MyFakeDataContextFake());</code></p> <p>Will become:</p> <pre><code> var fixture = new Fixture().Customize(new AutoMoqCustomization()); var sut = fixture.CreateAnonymous&lt;MyCommand&gt;(); </code></pre> <p>And that's it, this code will automatically create mocks for all the objects needed in the constructor of <code>MyCommand</code>.</p>
    singulars
    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. 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.
 

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