Mocking Private Methods and using MemberData Attribute xUnit

5 posts, 0 answers
  1. Shawn
    Shawn avatar
    11 posts
    Member since:
    Sep 2013

    Posted 27 Jul Link to this post

    I noticed some behavior with maybe xUnit and JustMock when testing private methods.   By below setup works fine and the tests run, however in my "MemberData" class, if i pass in more that one dataset for testing, then when the second time the test runs with the new set of data, the private method code never gets executed.   It gets to the "CreateUpdateFavoriteFacility" code in my api class and then just "steps over" the call to my private method. 

     

     

    Here is my Test Setup:

    [Theory]
            [MemberData("FacilityFavorite",
                MemberType =typeof(FavoriteTestData))]
            [Trait("BusinessTests", "FacilityTests")]
            public void CreateUpdateFavoriteFacility_CreateUpdateFavorites(Guid employeeID, Guid favoriteFacilityID)
            {
                //arrange
                var context = Mock.Create<jhaCommon>(Constructor.Mocked);
                var api = Mock.Create<JHADirectoryServiceAPI>(context);
     
                Mock.Arrange(() => api.CreateUpdateFavoriteFacility(Arg.AnyGuid, Arg.AnyGuid)).CallOriginal().MustBeCalled();
                Mock.Arrange(() => Logger.LogError(Arg.IsAny<Exception>())).OccursNever();
                Mock.Arrange(() => context.FavoriteTypes.Department()).Returns(() => FakeDataSource.FakeFavoriteTypes().Where(ft => ft.FavoriteType1.ToLower() == "department").FirstOrDefault());
                Mock.Arrange(() => context.PhonelistFavorites).ReturnsCollection(FakeDataSource.FakePhoneListFavorites());
     
                dynamic apiWrap = Mock.NonPublic.Wrap(api);
                Mock.NonPublic.Arrange(apiWrap.CreateUpdateFavorite(ArgExpr.IsAny<Guid>(), ArgExpr.IsAny<Guid>(), ArgExpr.IsAny<FavoriteType>())).CallOriginal();
                 
     
                //act
                var client = new JHADirectoryService(api);
                client.CreateUpdateFavoriteFacility(employeeID, favoriteFacilityID);
     
                //assert
                Mock.Assert(api);
            }

     

    Here is my TestDataClass

    public static class FavoriteTestData
        {
            #region Private Members
            private static List<object[]> _facilityFavorite = new List<object[]>
            {
                new object[] { new Guid("00000000-0000-0000-0000-000000000000") , new Guid("00000000-0000-0000-0000-000000000000") },
                new object[] { new Guid("11111111-1111-1111-1111-111111111111") , new Guid("11111111-1111-1111-1111-111111111111") }
                 
            };
            #endregion
     
            #region Public Properties
            public static IEnumerable<object[]> FacilityFavorite
            {
                get { return _facilityFavorite; }
            }
            #endregion
        }

     

    Here is my code in my client class.  This is the entry point of my test:

    public void CreateUpdateFavoriteFacility(Guid employeeID, Guid favoriteEmployeeID)
           {
               try
               {
                   _api.CreateUpdateFavoriteFacility(employeeID, favoriteEmployeeID);
               }
               catch (Exception ex)
               {
                   Logger.LogError(ex);
               }
           }

    Here is my "api" Code:

    public void CreateUpdateFavoriteFacility(Guid employeeID, Guid favoriteFacilityID)
    {
       CreateUpdateFavorite(employeeID, favoriteFacilityID, _context.FavoriteTypes.Department());
    }
    private void CreateUpdateFavorite(Guid employeeID, Guid favoriteObjectID, FavoriteType type)
    {
      //do stuff
    }

  2. Shawn
    Shawn avatar
    11 posts
    Member since:
    Sep 2013

    Posted 27 Jul Link to this post

    I've also found that when using Inline data, this happens too...

            [InlineData("55150DE3-5493-4E57-AAEF-9A7A9E576A88", "00000000-0000-0000-0000-000000000000")]
            [InlineData("55150DE3-5493-4E57-AAEF-9A7A9E576A88", "A159BAA4-725F-4DFF-8BA2-82C2073D87C5")]
            [InlineData("11111111-1111-1111-1111-111111111111", "A159BAA4-725F-4DFF-8BA2-82C2073D87C5")]

    If i run the inline data tests individually, things are fine.  But if i run them together, then it seems like something with how the NonPublic method is loaded up, it just never executes it during the same "Run"

  3. DevCraft R3 2016 release webinar banner
  4. Nikolay Valchev
    Admin
    Nikolay Valchev avatar
    72 posts

    Posted 29 Jul Link to this post

    Hello Shawn,

    Sorry for the inconvenience!
    We tried to reproduce both cases you reported us but, unfortunately, neither of them was successful. Could you create a small sample solution with this issues reproduced in it and send it to us, so we can investigate?

    Best Regards,
    Nikolay Valchev
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  5. Shawn
    Shawn avatar
    11 posts
    Member since:
    Sep 2013

    Posted 01 Aug in reply to Nikolay Valchev Link to this post

    Here is the attached .zipfile with the solution.   This contains a working service as well as a test project that runs 2 tests.  One succeeds and one fails with demonstrates the issue.

    To get the zip. just rename the TestService.gif to TestService.zip since this site won't allow you to upload anything but images.

  6. Nikolay Valchev
    Admin
    Nikolay Valchev avatar
    72 posts

    Posted 04 Aug Link to this post

    Hello Shawn,

    Thank you for the follow up!
    We've managed to reproduce your issue thanks to the solution you sent us!
    What I could understand from both of your examples (the one you initially sent us and the one contained in the TestService solution) is that you are trying to mock the creation of you api object but you still want the original definition of its methods to be called. If this is the case, I would recommend you just to instantiate the object with Mock.Create<T>(Behavior, params object[]) overload and pass Behavior.CallOriginal as behavior, this way no further arrangement of this instance would be needed (I've tested it with both of your examples and it worked).

    Best Regards,
    Nikolay Valchev
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
DevCraft R3 2016 release webinar banner