Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Hmm. a few things here mate.</p> <p>First, it looks like you're trying to test the a controller method. Great :)</p> <p>So this means, that anything the controller needs, should be mocked. This is because</p> <ol> <li>You don't want to worry about what happens inside that dependency.</li> <li>You can verify that the dependency was called/executed.</li> </ol> <p>Ok, so lets look at what you did and I'll see if i can refactor it to make it a bit more testable.</p> <p>-REMEMBER- i'm testing the <em>CONTROLLER METHOD</em>, not the stuff the controller method calls/depends upon.</p> <p>So this means I don't care about the service instance or the repository instance (which ever architectural way you decide to follow).</p> <p>NOTE: I've kept things simple, so i've stripped lots of crap out, etc.</p> <h3>Interface</h3> <p>First, we need an interface for the repository. This can be implemented as a in-memory repo, an entity framework repo, etc.. You'll see why, soon.</p> <pre><code>public interface ILESRepository { IQueryable&lt;Person&gt; GetAll(); } </code></pre> <h3>Controller</h3> <p>Here, we use the interface. This means it's really easy and awesome to use a mock <code>IRepository</code> or a real instance. </p> <pre><code>public class PersonController : Controller { private readonly ILESRepository _repository; public PersonController(ILESRepository repository) { if (repository == null) { throw new ArgumentNullException("repository"); } _repository = repository; } public ActionResult Index(int id) { var model = _repository.GetAll&lt;Person&gt;() .FirstOrDefault(x =&gt; x.Id == id); var viewModel = new VMPerson(model); return View(viewModel); } } </code></pre> <h3>Unit Test</h3> <p>Ok - here's the magic money shot stuff. First, we create some Fake People. Just work with me here... I'll show you where we use this in a tick. It's just a boring, simple list of your <code>POCO</code>'s.</p> <pre><code>public static class FakePeople() { public static IList&lt;Person&gt; GetSomeFakePeople() { return new List&lt;Person&gt; { new Person { Id = 1, Name = "John" }, new Person { Id = 2, Name = "Fred" }, new Person { Id = 3, Name = "Sally" }, } } } </code></pre> <p>Now we have the test itself. I'm using <code>xUnit</code> for my testing framework and <code>moq</code> for my mocking. Any framework is fine, here.</p> <pre><code>public class PersonControllerTests { [Fact] public void GivenAListOfPeople_Index_Returns1Person() { // Arrange. var mockRepository = new Mock&lt;ILESRepository&gt;(); mockRepository.Setup(x =&gt; x.GetAll&lt;Person&gt;()) .Returns( FakePeople.GetSomeFakePeople() .AsQueryable); var controller = new PersonController(mockRepository); controller.FakeOutContext(); // Act. var result = controller.Index(person.Id) as ViewResult; // Assert. Assert.NotNull(result); var model = result.Model as VMPerson; Assert.NotNull(model); Assert.Equal(1, model.Person.Id); Assert.Equal("John", model.Person.Username); // Make sure we actually called the GetAll&lt;Person&gt;() method on our mock. mockRepository.Verify(x =&gt; x.GetAll&lt;Person&gt;(), Times.Once()); } } </code></pre> <p>Ok, lets look at what I did.</p> <p>First, I arrange my crap. I first create a mock of the <code>ILESRepository</code>. Then i say: If anyone ever calls the <code>GetAll&lt;Person&gt;()</code> method, well .. don't -really- hit a database or a file or whatever .. just return a list of people, which created in <code>FakePeople.GetSomeFakePeople()</code>.</p> <p>So this is what would happen in the controller ...</p> <pre><code>var model = _repository.GetAll&lt;Person&gt;() .FirstOrDefault(x =&gt; x.Id == id); </code></pre> <p>First, we ask our mock to hit the <code>GetAll&lt;Person&gt;()</code> method. I just 'set it up' to return a list of people .. so then we have a list of 3 <code>Person</code> objects. Next, we then call a <code>FirstOrDefault(...)</code> on this list of 3 <code>Person</code> objects .. which returns the single object or null, depending on what the value of <code>id</code> is.</p> <p>Tada! That's the money shot :) </p> <p>Now back to the rest of the unit test.</p> <p>We <code>Act</code> and then we <code>Assert</code>. Nothing hard there. For bonus points, I <code>verify</code> that we've actually called the <code>GetAll&lt;Person&gt;()</code> method, on the mock .. inside the Controller's <code>Index</code> method. This is a safety call to make sure our controller logic (we're testing for) was done right.</p> <p>Sometimes, you might want to check for bad scenario's, like a person passed in bad data. This means you might never ever get to the mock methods (which is correct) so you <code>verify</code> that they were never called.</p> <p>Ok - questions, class?</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.
 

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