Mocking Private Methods

6 posts, 0 answers
  1. Shawn
    Shawn avatar
    12 posts
    Member since:
    Sep 2013

    Posted 12 Jul 2016 Link to this post

    I have a scenario that I cannot seem to get working just like i would like.

     

    I have been able to successfully write a test method against my private method just fine.

    Now, I'm trying to write a test against my public method.  In the public method, i want to the call to the private method to be mocked and return a mocked value so the remainder code in my public method will handle that result.

    However, when it comes time to execute the line of code in the public method that would call the private method, all that comes back is NULL.  I don't get my mocked value.

    Here is my current test

    var mockedClass = Mock.Create<JHADirectoryServiceAPI>(Constructor.Mocked);
     
    var autoFix = new Fixture();
    var otherPhoneDtoCollection_AM = autoFix.Create<IEnumerable<OtherPhoneDto>>();
      
    var inst = new PrivateAccessor(mockedClass);
     
    Mock.NonPublic.Arrange<IEnumerable<OtherPhoneDto>>(mockedClass, "GetOtherPhonesByOfficeID", Arg.AnyGuid)
                    .DoInstead(()=> inst.CallMethod("GetOtherPhonesByOfficeID", Arg.AnyGuid)).ReturnsCollection(otherPhoneDtoCollection_AM);

    Assume the below  code...

    Public IEnumerable<Object> GetDetails(Guid value)
    {
     
       //do some local stuff
        
       var result = GetOtherPhonesByOfficeID(value);
     
       //eval result
     
      return  myList
    }
     
    private  IEnumerable<OtherPhoneDto> GetOtherPhonesByOfficeID(Guid value)
    {
      //Do some Stuff
     
      return myList;
    }

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

    Posted 12 Jul 2016 in reply to Shawn Link to this post

    Figured it out.  Had to use the Mock.NonPublic.Wrap function as mentioned here.

    http://www.telerik.com/help/justmock/advanced-usage-mocking-non-public-members-and-types.html

    ultimately, this code snippet worked.

    dynamic mockedClassWrap = Mock.NonPublic.Wrap(mockedClass);
    Mock.NonPublic.Arrange<IEnumerable<OtherPhoneDto>>(mockedClassWrap .GetOtherPhonesByOfficeID(ArgExpr.IsAny<Guid>())).Returns(otherPhoneDtoCollection_AM);

     

  3. Svetlozar
    Admin
    Svetlozar avatar
    294 posts

    Posted 15 Jul 2016 Link to this post

    Hi,

    I am glad you've managed to resolve the issue. However I think there is something that you've missed - Mock Behaviors

    When you create a mock with Mock.Create and don't specify the behavior, its member implementation are empty stubs (because of the default behavior). Although you've arranged the private method, the public method has an empty implementation that doesn't call the original method (that calls the private method). To achieve what you want you have to create the mock with CallOriginal behavior. I prepared a small example. Consider that code

    public class Student
    {
        public string GetName()
        {
            return GetPrivateName();
        }
     
        private string GetPrivateName()
        {
            return "Svetlozar";
        }
    }

    Here is how to arrange the private method and leave the public one with the original implementation.

    [TestMethod]
    public void TestMethod1()
    {
        var mocked = Mock.Create<Student>(Behavior.CallOriginal);
        Mock.NonPublic.Arrange<string>(mocked, "GetPrivateName").Returns("Svetlio");
        Assert.AreEqual("Svetlio", mocked.GetName());          
    }

    I hope that makes sense. Let us know if you have other questions. 

    Regards,
    Svetlozar
    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
  4. Stephan
    Stephan avatar
    1 posts
    Member since:
    Nov 2017

    Posted 11 Nov Link to this post

    Is there no better why to test if a protected or a private method was called? I know it from mockito in the java work there I can check if a "package" method was called like a public method. 

    I do not like that I have to call for example:

      Mock.NonPublic.Arrange<string>(mocked, "GetPrivateName").Returns("Svetlio");

    Is there no better way that I not need to write "GetPrivateName" by myself. I like to have a way that if can find the methods in intellisense...

     

  5. Kammen
    Admin
    Kammen avatar
    313 posts

    Posted 2 days and 22 hours ago Link to this post

    Hi Stephan,

    Thank you for the interest in JustMock.

    Can you be more specific how exactly do you expect a non-public method call should look? Right now, JustMock uses expressions to access the public APIs, however this is not the case with private APIs since they are not accessible.

    If you have good idea we'll be really happy to look deeper into it and estimate it.

    Thanks,
    Kammen
    Progress Telerik
    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
  6. Stephan
    Stephan avatar
    1 posts
    Member since:
    Oct 2017

    Posted 2 days and 7 hours ago Link to this post

    Hi Kamman

    I worked the last 2 years with java. There its possible to test easy if a package-internal method was called (classes must have the same package)

    See example:

    Class to Test:

    package [xy].web.client.application.article.detail;

    [imports]


    public class ArticleDetailFragment  {

    ....

    @Inject
    public ArticleDetailFragment(...){
    ...
    }



    @Override
    public void start() {
    ...
    loadMasterData();
    loadArticle();
    }



    void loadMasterData() {
    ...
    }

    void loadArticle() {
    ...
    }
    }

     

    TestClass:


    package xy.web.client.application.article.detail;

    [imports]

    @RunWith(MockitoJUnitRunner.class)
    public class ArticleDetailFragmentTest {

    private ArticleDetailFragment presenter;

    @Before
    public void setup() {
      presenter = new ArticleDetailFragment(...);
    }

    @Test
    public void start() {
      // Arrange
      presenter = spy(presenter);
      // Act
      presenter.start();
      // Assert
      verify(view).setPresenter(presenter);
      verify(presenter).loadMasterData();
      verify(presenter).loadArticle();
      }
    }

Back to Top