1

I've been trying to figure out how to unit test my application but I don't quite understand how everything fits together.

I have followed John Papa's tutorial on PluralSight (SPA) and built my model, repository and unit of work in the exact same way. Unfortunately, he doesn't provide any examples on how we can unit test this.

I have played around with Moq and found very few links online that explain how to do so, but unfortunately I got nowhere.

Some code to provide context :

public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
    T GetById(int id);
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(int id);
}

public interface IFeedbackRepository : IRepository<Feedback>
{
    IQueryable<Feedback> GetByFeedbackFor(int id);
}

public class FeedbackRepository : EFRepository<Feedback>, IFeedbackRepository
{
    public FeedbackRepository(WebAppDbContext context) : base(context) { }
    public IQueryable<Feedback> GetByFeedbackFor(int id) 
    {
        return DbSet.Where(f => f.FeedbackForId == id);
    }
}

public interface IWebAppUow
{
    void Commit();

    IFeedbackRepository Feedbacks { get; }
}

   public void TestMethod1()
    {
     Mock<IWebAppUow> mockUnitOfWork = new Mock<IWebAppUow>();

    // THEN ??
    }

Edit: I have found this link ( http://msdn.microsoft.com/en-us/data/dn314429.aspx ) which explains how to do it but works directly on the DbSet. If someone could explain how we could modify this example to use UoW and Repository pattern that would be grand!

3
  • You need to mock IWebAppUow if you are going to test some code that use it. So it's hard to answer your question not seeing whay actual code you want to test. Commented Nov 10, 2013 at 10:43
  • Let's say I have the following in my FeedbackRepository: public Feedback GetByIds(int feedbackForId, int feedbackFromId) { return DbSet.FirstOrDefault( f => f.FeedbackForId == feedbackForId && f.FeedbackFromId == feedbackFromId ); } Commented Nov 10, 2013 at 10:46
  • Then you probably want to mock your repository instead. Commented Nov 10, 2013 at 13:36

3 Answers 3

1

If you are new to Unit Testing, testing EF is not the best way to start because it is pretty hard to mock its context and all the API. I would recommend following some simpler examples.

For EF unit testing, I would recommend you to check into Effort frame work. Here is what it explains on its website

Effort is a powerful tool that enables a convenient way to create automated tests for Entity Framework based applications. It is basically an ADO.NET provider that executes all the data operations on a lightweight in-process main memory database instead of a traditional external database. It provides some intuitive helper methods too that make really easy to use this provider with existing ObjectContext or DbContext classes. A simple addition to existing code might be enough to create data driven tests that can run without the presence of the external database.

Sign up to request clarification or add additional context in comments.

1 Comment

I've done plenty of Unit Testing before but not on ASP.NET or WebApplicatios in general..
1

I would not unit test your repository, the DbContext is a concrete class that depends on a real database, as far as I know, I can't mock it with Moq. So what I do is focus on unit testing the codes that uses the repository and mock the repositories instead.

To actually test your repository, I'd go with integration tests.

8 Comments

The code that uses the repository would be the Uow which in turn is used by the controller. Are you suggesting unit testing that instead?
I'm not sure of that architecture. The architecture I'm familar with is that a service would depend on the UoW and a repository, you would mock both of those and unit test the service method.
I followed the architecture that John Papa used in hia SPA pluralSight tutorial. Do you have a tutorial for the one who are discussing? I must admit I was never into my architecture, I usually kept it as simple as possible, but with this project I am trying to get it right from the start. Maintainable, scalable and easy for new comers to jump in.
@teh0wner, take a look at this example of the onion architecture: github.com/shawnmclean/OnionArchitecture
Just going through that solution and I am glad you suggested it to me! The separation of concerns is quite clear, loosely coupled but one thing I was wondering; OnionArchitecure.Infrastructure has 2 empty folders. What would usually go in there?
|
1

So, if I've understood correctly your comment you want to test methods of your FeedbackRepository class. Let's look how to do it for GetByFeedbackFor method.

You are passing WebAppDbContext context in your FeedbackRepository. It's not very good. Probably you will not be able to test this code. You should extract IWebAppDbContext interface and pass it in FeedbackRepository ctor.

I don't know what is behind this code return DbSet.Where(f => f.FeedbackForId == id); so I can only guess that this is some property of base class... But if assume that you are using context here not DbSet property your test method will look like next (I think it will be not too hard to rewrite it in case of base property (or may be even it will work as is)):

public void ShouldReturnFeedbacksForCorrectId()
{
  var contextMock = new Mock<IWebAppDbContext>();

  // fill expected for example with 2 entities with FeedbackForId == 1
  IQueryable<Feedback> expected = InitWithDataSomehow();
  contextMock.Setup(i => i.Feedbacks).Returns(expected);
  var repositoryUnderTest = new FeedbackRepository(contextMock);

  IQueryable<Feedback> actualResult = repositoryUnderTest.GetByFeedbackFor(1);

  Assert.AreEqual(expected, actualResult);
}

2 Comments

You have understood right. I'll extract WebAppDbContext to an Interface and see if that works! Will get back to you as soon as I give this a shot.
My WebAppDbContext extends IdentityContext<ApplicationUser> which is used in ASP.NET Identity.. how would I go on about doing that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.