New to Mocking; working with Entity Framework

12 posts, 0 answers
  1. Nathan J Pledger
    Nathan J Pledger avatar
    95 posts
    Member since:
    Apr 2006

    Posted 19 Jan 2011 Link to this post

    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


  2. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 21 Jan 2011 Link to this post

    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
  3. DevCraft R3 2016 release webinar banner
  4. NaHoG
    NaHoG avatar
    2 posts
    Member since:
    Mar 2013

    Posted 13 Mar 2013 Link to this post

    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
  5. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 13 Mar 2013 Link to this post

    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.
  6. NaHoG
    NaHoG avatar
    2 posts
    Member since:
    Mar 2013

    Posted 04 Apr 2013 Link to this post

    With some modification, the use of ReturnsCollection worked ok me.

    Thanks you Kaloyan
  7. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 05 Apr 2013 Link to this post

    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.
  8. Ray
    Ray avatar
    4 posts
    Member since:
    Apr 2013

    Posted 12 Apr 2013 Link to this post

    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?

  9. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 15 Apr 2013 Link to this post

    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.
  10. SPAR ITSG
    SPAR ITSG avatar
    1 posts
    Member since:
    Dec 2012

    Posted 18 Apr 2013 Link to this post

    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);
  11. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 19 Apr 2013 Link to this post

    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.
  12. Ray
    Ray avatar
    4 posts
    Member since:
    Apr 2013

    Posted 07 May 2013 Link to this post

    Thanks Kaloyan ,
    That was it, am getting consistant results now.

    Best regards,
    Ray
  13. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 07 May 2013 Link to this post

    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.
Back to Top
DevCraft R3 2016 release webinar banner