This is a migrated thread and some comments may be shown as answers.

New to Mocking; working with Entity Framework

11 Answers 325 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Nathan J Pledger
Top achievements
Rank 2
Nathan J Pledger asked on 19 Jan 2011, 12:15 PM
Hi,

I'm new to mocking and am playing with JustMock to mock Entity Framework 4. Therefore, my understanding of what I want to happen may be a reflection of my lack of understanding of mocking principles/implementation.

I have browsed around and found some resources, but they're not all that clear. Have seen:
What I want to do is establish a mock of my EF entities, and access them without database.

So far, I have:

var entitiesMock = Mock.Create<Entities>();

This still wants the ConnectionString to appear in the app.config file of the Test DLL, which I would hope wouldn't be required? Without it, the default constructor throws an exception. Question 1: So am I right in thinking any unit tests I mock in this way are dependant on the DB - sort of making it a bit pointless?

My next task is to create an object and add it to the mocked entities:

UserAccount userAccount = new UserAccount()
{
    Username = "UserName",
    Password = "Password"
};
 
// Arrange
List<UserAccount> userAccounts = new List<UserAccount>();
Mock.Arrange(() => entitiesMock.AddToUserAccounts(Arg.IsAny<UserAccount>())).DoInstead(()=>userAccounts.Add(userAccount));
             
// Act
entitiesMock.AddToUserAccounts(userAccount);
 
// Assert
Assert.AreEqual(1, userAccounts.Count);
Assert.AreSame(userAccount, userAccounts[0]);

I understand this, and my object does indeed appear in the userAccounts collection. Win.

So in my head, I have an entity framework entities collection that I have mocked and primed with a user account. I would like to pass that into another class:

Authentication authentication = new Authentication(entitiesMock);
UserAccount authenticatedUserAccount=authentication.Authenticate(userAccount.Username, userAccount.Password, Authentication.PasswordFormat.PlainText);
Assert.AreEqual(userAccount.Username, authenticatedUserAccount.Username);

This uses the EF Model to return the user and authenticate their details.

This leaves the Question 2: when this code runs, the UserAccounts collection within the mocked Entities object is (understandably) null. Where am I going wrong? Am I wrong to expect to be able to prime the mocked entities with a single object and be able to use that?

Any help appreciated, I've made time in my project to work on Mocking and I need to get to grips with this fast!

Nathan


11 Answers, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 21 Jan 2011, 01:01 PM
Hi Nathan,

Thanks for bringing up the questions.

On your first issue, if target type is not sealed then JusMock tries to create the mock and implement its members (virtual) using proxy thus it does not need a profiler to intercept the ones which can be intercepted via simple inheritance.Therefore, it fires the default constructor which on the other hand requires a connection string in your config file for entity framework mocking (This behavior is similar to Moq)

But in certain cases, it is not expected / possible.  Therefore, we recently added a way to specify that you want the constructor to be mocked as well. You will be able to do this through an additional parameter in Mock.Create<T>:


var entities = Mock.Create<Entities>(Constructor.Mocked);

This will be available in the coming Q1 release.

Next, for your second issue i am attaching a test project that shows an example to supply the mocked entity in a nested class and assert it accordingly.

In that particular example I have created the .edmx from NorthWind database and written the test in the following way:

var entities = Mock.Create<NorthwindEntities>();
              
            Category category = new Category()
            {
                CategoryName = "Beer"
            };
  
            // Arrange
            List<Category> categories = new List<Category>();
            Mock.Arrange(() => entities.AddToCategories(Arg.IsAny<Category>())).DoInstead(() => categories.Add(category));
  
            Inventory inventory = new Inventory(entities);
  
            inventory.PlaceOrder(category);
  
            // Assert
            Assert.AreEqual(1, categories.Count);
            Assert.AreSame(category, categories[0]);


Finally, sorry for the documentation issue of "Cropping code"; we will fix that as soon as possible and please do feel free to write us back for any further issues.

Kind regards,
Ricky
the Telerik team

Browse the videos here>> to help you get started with JustMock
0
NaHoG
Top achievements
Rank 2
answered on 13 Mar 2013, 03:09 PM
I downloaded the demo code, and this works fine for mocking "inserting" part of EF.

There is a way to mock the enumerable part of ObjectContext in a way to provide fake data?

Regards,
Nic
0
Kaloyan
Telerik team
answered on 13 Mar 2013, 04:27 PM
Hello Nicolas,

Thank you for the question.

Yes, it is possible to return fake data. To assist you further, please check the following example:
[TestMethod]
public void ShouldFakeDBCollectionReturn()
{
    // Creating fake collection that should be returned in the fake DB
    List<Category> fakeCategories = new List<Category>();
    fakeCategories.Add(new Category { CategoryID = 32 });
    fakeCategories.Add(new Category { CategoryName = "Telerik" });
 
    // Arrange
    var entities = Mock.Create<NorthwindEntities>();
                 
    Mock.Arrange(() => entities.Categories).ReturnsCollection(fakeCategories);
 
    // Act
    var actualCategories = entities.Categories;
 
    // Assert
    Assert.AreEqual(2, actualCategories.Count());
}

I have also attached the example project with the included new test method in it. I hope it works for you.

Please give us a note either if you require further assistance about this matter or anything else concerning JustMock.

All the best,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
NaHoG
Top achievements
Rank 2
answered on 04 Apr 2013, 05:42 PM
With some modification, the use of ReturnsCollection worked ok me.

Thanks you Kaloyan
0
Kaloyan
Telerik team
answered on 05 Apr 2013, 07:18 AM
Hello Nicolas,

I am happy, I could help you.

Please contact us again, if you need anything else.

Greetings,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Ray
Top achievements
Rank 1
answered on 12 Apr 2013, 11:02 AM
Hi I have an issue with a very simple mock test:

[TestMethod]

public void GetMockUnknownUserByName()

 {

//Arrange

 var User = Mock.Create<CtrUser>();

 Mock.Arrange(()=>User.Login).Returns("GLOBAL\\unknown"); //ensure User.Login returns Global\unknown

 
//Act

 var mocked = User.Login;

 

//Assert

 Assert.AreEqual("GLOBAL\\unknown", mocked);

}
This test passes when run on it's own but when run with other tests it fails with:
Failed GetMockUnknownUserByName Riana.Tests Assert.AreEqual failed. Expected:<GLOBAL\unknown>. Actual:<>.  

I believe it may have something to do with the way the CtrUser Class is constructed. (although why the outcome depends on how many test are run bothers me)
I'm using it in a factory pattern and it's constructor is private

 

public static CtrUser NewUser()

 {

     return DataPortal.Create<CtrUser>();

 }

 

private CtrUser()

 { /* require use of factory method */ }

 
i have also tried :
var User = Mock.Create(()=>CtrUser.NewUser());

 but this fails with:

 System.NullReferenceException: Object reference not set to an instance of an object.

I know the solution is probably very simple, but how can I mock a property of a class constructed from a static factory method?

0
Kaloyan
Telerik team
answered on 15 Apr 2013, 02:20 PM
Hi again Ray,

Thank you for reaching back to us.

The cause of this matter, could be that the CtrUser class has been already JIT compiled when the test is intercepting the mock. That is why this test will pass when run on its own and may fail along with other tests.

To avoid this, I would suggest to initialize the "CtrUser" class in the [ClassInitialize] or in the constructor of your test class. Below, you will find an example:
[TestClass]
public class JustMockTest
{
    public JustMockTest()
    {
        Mock.Initialize<CtrUser>();
    }
 
    [TestMethod]
    public void GetMockUnknownUserByName()
    {
        //Arrange
        var User = Mock.Create<CtrUser>();
 
        Mock.Arrange(() => User.Login).Returns("GLOBAL\\unknown"); //ensure User.Login returns Global\unknown
 
        //Act
        var mocked = User.Login;
 
        //Assert
        Assert.AreEqual("GLOBAL\\unknown", mocked);
    }
Here, I am initializing the "CtrUser" class inside the constructor of my test class. You can use the same initialization method in [ClassInitialize]

I hope this helps.

Regards,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
SPAR ITSG
Top achievements
Rank 1
answered on 19 Apr 2013, 12:50 AM
Here's another solution (using JustMock v 2013.1.315.0):
I'm on a project that has multiple hands, and a remote dev database. We use an abstract base class for data access with the following:
public abstract class DataAccessBase
{
Entities data;
protected Entities ProjectEntities
{
get { return data; }
set { data = value; }
}
public DataAccessBase()
{
data = new Entities();
}
public DataAccessBase(string connString)
{
data = new Entities(connString);
}
}


This way, from the test we can call:
 
OwnerData data = new OwnerData(ConfigurationManager.ConnectionStrings["USTEntities"].ConnectionString);


and then after the object is populated:

List<QAQC> history = new List<QAQC>();
Mock.Arrange(() => data.SaveAuditTrail(Arg.IsAny<QAQC>())).DoInstead(()=> history.Add(histObj));
data.SaveAuditTrail(histObj);
Assert.AreEqual(1, history.Count());
Assert.AreEqual(pk, history[0].PrimaryKey);
0
Kaloyan
Telerik team
answered on 19 Apr 2013, 02:35 PM
Hello SPAR ITSG,

Great point! Thank you for sharing this.

Kind regards,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
0
Ray
Top achievements
Rank 1
answered on 07 May 2013, 01:48 PM
Thanks Kaloyan ,
That was it, am getting consistant results now.

Best regards,
Ray
0
Kaloyan
Telerik team
answered on 07 May 2013, 01:52 PM
Hi Ray,

I am glad the issue is solved now.

Do not hesitate to contact us again, if you need further assistance.

All the best,
Kaloyan
the Telerik team
Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
Tags
General Discussions
Asked by
Nathan J Pledger
Top achievements
Rank 2
Answers by
Ricky
Telerik team
NaHoG
Top achievements
Rank 2
Kaloyan
Telerik team
Ray
Top achievements
Rank 1
SPAR ITSG
Top achievements
Rank 1
Share this question
or