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

Mocking Private Methods

6 Answers 735 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Shawn
Top achievements
Rank 1
Shawn asked on 12 Jul 2016, 02:30 PM

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;
}

6 Answers, 1 is accepted

Sort by
0
Shawn
Top achievements
Rank 1
answered on 12 Jul 2016, 08:39 PM

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);

 

0
Svetlozar
Telerik team
answered on 15 Jul 2016, 12:46 PM
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
0
Stephan
Top achievements
Rank 1
answered on 11 Nov 2017, 08:39 PM

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...

 

0
Kammen
Telerik team
answered on 20 Nov 2017, 03:40 PM
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
0
Stephan
Top achievements
Rank 1
answered on 21 Nov 2017, 06:59 AM

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();
  }
}

0
Kammen
Telerik team
answered on 24 Nov 2017, 10:25 AM
Hi Stephan,

If I understand your sample correctly, in Java you can easily mock package-internal methods from tests located in the same package.

If this is the case, I'm glad to confirm that this is achievable in .NET world too. Even more, since .NET 2.0, you can mark a project as internal visible, so you can test class' internal methods from another project. For more information, I'm suggesting this article.

However, I'm not aware of a way that you can access private members outside a class other than using Reflection. And using the Mock.NonPublic, PrivateAccessor and other helper classes just does this for you.

Hope this answers your questions. If you need further information, do not hesitate to contact me.

Regards,
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
Tags
General Discussions
Asked by
Shawn
Top achievements
Rank 1
Answers by
Shawn
Top achievements
Rank 1
Svetlozar
Telerik team
Stephan
Top achievements
Rank 1
Kammen
Telerik team
Stephan
Top achievements
Rank 1
Share this question
or