Help getting started using Moq for Entity Framework

  • (2 Pages)
  • +
  • 1
  • 2

19 Replies - 1398 Views - Last Post: 14 January 2016 - 07:31 AM Rate Topic: -----

#1 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 06:55 AM

I've recently been asked to write some unit tests for our code at work. For the most part this is fairly easy to do, however a lot of the code in one of our products links in with Entity Framework. I've downloaded Moq but I'm getting a bit stuck as to how to actually use it for unit testing. For this example I've picked the easiest method which I want to test:

Method that needs testing:
public static Entity getEntity(IUnitOfWork database, string entityName)
{
    Entity _entity = database.EntityRepo.Find(x => x.Name.ToLower().Trim() == entityName).FirstOrDefault();
    return _entity;
}


Where IUnitOfWork represents our database. I've attempted to use Moq in the following way, but I don't think it's quite what I should be going for:

[TestMethod]
public void anotherTest2()
{
    Entity testEntity = new Entity();
    testEntity.Name = "Test";

    var mockService = new Mock<IUnitOfWork>();
    IUnitOfWork testDB = mockService.Object;
    testDB.EntityRepo.Add(testEntity);

    Entity testEntity2 = EntityHelper.getEntity(testDB,testEntity.Name);
    int count = testDB.EntityRepo.Count();

    Assert.AreEqual(testEntity.Name,testEntity2.Name);
            
}


What I've tried to do is set-up a Moq instance of our database and entity repo, add the new entity to that repo and then try to get it back using the getEntity method. Everything compiles ok, however it doesn't look like my Entity object is ever added (I've tested this using Count and it comes back as 0).

How can I add an Entity object to my Moq so that I can test if it returns ok? Is this even the right approach? I've noticed others using .Returns() which specifies what exactly should be returned, but I'm unsure where I should be adding that here (if at all).

Please excuse me if I'm missing something blindingly obvious, I'm really new to Entity Framework and Moq! :)/>

Is This A Good Question/Topic? 0
  • +

Replies To: Help getting started using Moq for Entity Framework

#2 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 07:43 AM

Since you have a mock object, even your call to Add() on line 9 calls a mock. Since by default mocks don't do anything, that call effectively didn't add anything into the repository.

You are on the right track that you have to configure the EntityRepo to return a collection that contains the entity you are looking for.
Was This Post Helpful? 0
  • +
  • -

#3 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 07:54 AM

Ah I see! So a mock won't return anything, that makes sense. I've changed my code to explicitly state what should be returned however I've run into an issue; the following code won't compile as it says that Moq doesn't contain a definition for Returns() (which is really odd since every tutorial I've read uses it).

[TestMethod]
public void anotherTest()
{
    Entity testEntity = new Entity();
    testEntity.Name = "Test";

    var mockEntityRepo = new Mock<DatabaseRepository<Entity>>();
    mockEntityRepo.Setup(mock => mock.Add(It.IsAny<Entity>())).Returns(testEntity);
            
}


I can't see why Moq isn't happy with Returns(), this is the general syntax for nearly all tutorials I've seen.
Was This Post Helpful? 0
  • +
  • -

#4 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 08:27 AM

The reason why the compiler wasn't happy with the .Returns in my previous post was because the 'Add' method is void, and doesn't return anything. After trying a different method (getByID) it was happy as this does return a value.

mockEntityRepo.Setup(mock => mock.getByID(It.IsAny<int>())).Returns(testEntity);


Does anyone know how I can test void methods? For example, the Add() method in my previous post is a void method. I was thinking along the lines of doing a search in the 'Returns()' section of the code but then we're back to square one; the compiler won't compile it as Add() is void and doesn't return anything.
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 08:34 AM

You are headed the wrong direction. You want your mock EntityRepo to return a collection that includes the entity. See the "Properties" section of the moq quick start.

(Currently very sad about the move of moq from Google code to Github. They seem to have lost the other wiki pages. One of the wiki pages used to show how to return a collection as well as how to mock IEnumerable<T>. Hopefully, they'll rebuild the other pages.)
Was This Post Helpful? 0
  • +
  • -

#6 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 08:46 AM

So the approach I want to go after is:

1) Create a collection of Entity objects
2) Add Entity(s) to that collection (including the one I want to search my repo for)
3) Have my mockEntityRepo return that collection

I've taken a look at the quick start guide but I don't understand how returning the collection is an accurate mock of the getByID method (which only returns 1 item)?

Thank you for being patient with me too, I'm sure this all sounds very tedious for those looking in who know what they are doing!!
Was This Post Helpful? 0
  • +
  • -

#7 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 08:55 AM

Why would you need to mock getById() when the code you are testing is:
database.EntityRepo.Find(x => x.Name.ToLower().Trim() == entityName).FirstOrDefault();


Was This Post Helpful? 0
  • +
  • -

#8 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 09:05 AM

See post #3; I had changed my code to test for a different method (the Add() method) (admittedly I should have made that more clear, however as of yet I'm unable to edit my posts). From there I ran into problems as .Returns() wasn't compiling. I since found out that was because my Add() is void and Returns() only works if the method in question returns something. As such I tested it with another method that does return something (getByID()) and that seemed to be happy with Returns().

My 2 issues now are that:

1) I don't know how to test a mock method that is void (in this case, Add())
2) I'm unsure how returning the collection is an accurate test for a method that only returns 1 specific value (getByID)
Was This Post Helpful? 0
  • +
  • -

#9 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 09:07 AM

But you are not testing anything in post #3. You are simply setting up a mock.
Was This Post Helpful? 0
  • +
  • -

#10 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 09:10 AM

I substituted the .Add() post #2 with the getByID() line of code in post #3.
Was This Post Helpful? 0
  • +
  • -

#11 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 09:15 AM

I think we are getting out of sync with all the back references to older posts. Let's get back in sync. Post your new unit test, and the method that you want to test.
Was This Post Helpful? 0
  • +
  • -

#12 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 09:41 AM

Also, I think you are missing the point of mocking. The point of IoC and mocks is so that you can test your code, not somebody else's code. So that means that you aren't testing whether a database successfully stores or retrieves data. Instead you are testing that your data access layer is making the correct calls into the database.
Was This Post Helpful? 0
  • +
  • -

#13 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 09:53 AM

Ok good call; I currently have this method:

public static Entity saveAndGetNewEntity(IUnitOfWork database, string entity, bool loadDriving)
{
    Entity _entity = new Entity();
    _entity.Name = entity.Trim();
    _entity.Alias = entity.Trim();
    _entity.Client = database.ClientsRepo.GetAll().First();
    _entity.LoadDrivingSource = loadDriving;
    database.EntityRepo.Add(_entity);
    database.commit();

    return _entity;
}


I have attempted the following (also I'm aware there's no assert or checks, at this moment in time I just want to get it setup correctly):
[TestMethod]
public void SaveAndGetNewEntity_SaveEntity_EntityReturned()
{
    Entity testEntity = new Entity();
    testEntity.Name = "Test";
    testEntity.ID = 1;

    var mockEntityRepo = new Mock<DatabaseRepository<Entity>>();
    mockEntityRepo.Setup(mock => mock.Add(testEntity));

}


The target method in question is saveAndGetNewEntity(). Inside this method the Add() method is called (as well as GetAll(), but I'm just focused on Add() for now). I do not know how to properly test the saveAndGetNewEntity() method. I have attempted to mock the Add() method which does work but I feel that this doesn't test completely what saveAndGetNewEntity() does. For example, saveAndGetNewEntity() returns the entity that you've just added; I don't know how to test that it is returning the right thing (or even if I should be testing it at all).

You mentioned about checking if the data access layer is making the correct calls to the database; I think that is where I'm getting confused. Ultimately that is what I don't know how to test, all I can do is post what I've done and have someone point me in the right direction! :)
Was This Post Helpful? 0
  • +
  • -

#14 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7192
  • View blog
  • Posts: 24,370
  • Joined: 05-May 12

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 10:04 AM

In your unit test you'll want to do the following:
  • Call saveAndGetNewEntity().
  • Assert that you get back a non-null Entity object.
  • Assert that the Name of the object matches the trimmed version of the string that you passed in.
  • Assert that the Alias of the object matches the trimmed version of the string that you passed in.
  • Assert that the LoadDrivingSource matches the integer that you passsed in.
  • Assert that the Client is not null.
  • Assert that mockEntityRepo.GetAll() got called at least once. (You may want a stronger assert that it get called exactly once if you care about performance.)
  • Assert that mockEntityRepo.Add() gets called only once.
  • Assert that mockEntityRepo.commit() gets called only once.


Additionally:
  • Assert that the entity passed to mockEntityRepo.Add() matches the entity that you got back; OR
  • Assert that the entity object passed to mockEntityRepo.Add() has the expected values for Name, Alias, LoadDrivingSource, and Client.

Was This Post Helpful? 0
  • +
  • -

#15 Novastorm   User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 11
  • Joined: 13-January 16

Re: Help getting started using Moq for Entity Framework

Posted 13 January 2016 - 10:10 AM

Cool thanks! In order to call saveAndGetNewEntity() I need to pass in an IUnitOfWork object, how would that work? IUnitOfWork is an interface that represents our database.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2