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

Future Objects support?

15 Answers 175 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Vincent
Top achievements
Rank 1
Vincent asked on 05 Jan 2011, 09:14 PM
Hi all,

 I was wondering if JusyMock could easily "intercept" object creation and replace them with fakes created on the fly?

I'm trying to unit test a method that, amongs other things, creates an instance of an object of a certain type and then uses it.  The instance is NOT injected into the method and so I cannot control what instance is used inside the method...

I know that some other mocking framework do support Future Objects mocking.  Is it the case with JustMock ?

Thanks for your time,

Vincent Grondin

EDIT:   I think I need the "Weaver" library to accomplish this, can someone from telerik tell me if this library is included in the FREE version of JustMock? 

15 Answers, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 07 Jan 2011, 03:21 PM
Hi Vincent,

Thank you for raising the question. Good news is that it is possible to mock future objects using the current build of JustMock (commercial / full). To best simulate the scenario, let's consider a method that internally creates the instance of login service to validate a particular user:


public class LegacyCode
{
    public int CheckUser(string userName, string password)
    {
        var _service = new LoginService();
        return _service.ValidateUser(userName, password);
    }
}

Note that the instance is created on the fly and the target class does not accept the instance of LoginService via dependency injection.

Next, we have our LoginService class that we are going to mock (stripped for this post):

public class LoginService 
{
    public int ValidateUser(string userName, string password)
    {
        int userID = 5;
        return userID;
    }
}

Moving forward, JustMock does not require any extra construct to mock future objects. Therefore, we can simply write our test in the following way:

[TestMethod]
    public void Should_Assert_Behavior_On_Concrete_Class()
    {
        string userName = "User";
        string password = "Pwd";
        bool asserted = false;
        LoginService service = new LoginService();
        Mock.Arrange(() => service.ValidateUser(userName, password)).DoInstead(() => asserted = true);
        var sut = new LegacyCode();
        sut.CheckUser(userName, password);
        Assert.IsTrue(asserted);
        Mock.Assert(service);
    }


Since we have simply created the instance, the test will work if the method is either final or virtual. But if we create a mocked instance via Mock.Create<LoginService>() then it will only work if the method is final because Mock.Create builds proxied instance for non-sealed classes and therefore initializes the virtual methods via proxy (simpler and faster than profiler).

Overall, if you want to create future objects simply create the instance of the target class via new keyword in that regard there is no need to do Mock.Create<T> unless it is sealed. 

Finally, I have attached the test project to let you have a look and please do feel free to write us back for any further issues.


P.S. The post applies to commercial edition only (also can be tested using the trial build)

Kind Regards,
Ricky
the Telerik team
Browse the videos here>> to help you get started with JustMock
0
Vincent
Top achievements
Rank 1
answered on 07 Jan 2011, 07:03 PM
I downloaded the FREE edition of JustMock... I didn't pay for anything.  Does this mean the above won't work?
0
Ricky
Telerik team
answered on 10 Jan 2011, 09:23 AM
Hi Vincent,

Thanks again for the post. Regarding "Mocking future object", as it is done through profiler that is not free therefore you can't do that in the free version. For free version the only way is to send the mocked object via dependency injection.

Should you have any more issues, please don’t hesitate to contact us.

Kind regards,
Ricky
the Telerik team
Browse the videos here>> to help you get started with JustMock
0
Vincent
Top achievements
Rank 1
answered on 10 Jan 2011, 05:04 PM
Alright, thank you very much.

I now have the full version of JustMock (not the free edition) which I got with the MS MVP offer from telerik.   The exemple above sent as an attachment still fails...  One thing I'm wondering is this:

The "Arrange" line, under the covers, is it saying replace the call to ValidateUser IN ALL FUTURE INSTANCES of type LoginService or does it ONLY apply to the instance used in the arrange statement (local variable of the unit test) ?

I thought it would only apply to the instance of LoginService used in the arrange statement which is local to the unit test and would therefore be sort of useless in my case....

I'm still without luck on this issue...  I run the Unit Test that was provided in this post without success...
0
Vincent
Top achievements
Rank 1
answered on 10 Jan 2011, 05:17 PM
OK my mistake I forgot to ENABLE Telerick Just Mock in the VS2010 menu....  MY fault....

So I guess this confirms the Arrange applies to all future instances of a type...

Thanks for your time!
0
Vincent
Top achievements
Rank 1
answered on 10 Jan 2011, 07:55 PM
One last question regarding this post...

In the sample presented above, we replace the call to ValidateUser in the LoginService with a lambda that flags a bool to True....  That I understand...  My original question was related to the creation of future objects...

How would I proceed to make sure that the CONSTRUCTOR for the LoginService is NEVER CALLED....  Suppose that the LoginService constructor does some evil thing and we do not want this line to be executed:

 

 

public class LegacyCode
{
    
public int CheckUser(string userName, string password)
    {
      ---->  
LoginService _service = new LoginService();
        
return _service.ValidateUser(userName, password);
    }
}

 

 

 


... and instead, the _service variable is loaded with a predefined LoginService MOCK.   How can I accomplish this?
I would assume this would be done using some sort of arrange but not on the future method calls of the instance but an arrange on the creation of the object itself....  Any ideas?


What I want is a way to tell the mocking framework:  "Whenever you see an object of type X created, replace the creation (call to the constructor and all) with this Mock"...

Any chance this can be done with JustMock? 

0
Ricky
Telerik team
answered on 13 Jan 2011, 11:53 AM

Hi Vincent,

Thanks again for making the post. 

As we are keeping things as explicit as possible therefore using JustMock to create a mocked object you must need to use Mock.Create or less it will be like a normal create new. Therefore, there won’t be any hidden replace via profiler. This actually eliminates ambiguity and thus makes things simpler.

However, when you create a mocked instance using Mock.Create, it calls the default constructor or  the specific constructor based on the arguments passed in or constructor mentioned via lambda (Similar to Moq / Rhino).

Although for class with no default constructor, Mock.Create does create the instance without calling any constructor. But in your case, if LoginService has a default constructor then for that i am adding a task that will give you an additional option whether to mock the constructor when creating the instance via Mock.Create.

You can further track the issue here:
http://www.telerik.com/support/pits.aspx#/public/justmock/4608


Finally, hope that answers your question and please do feel free to write back for any other issues. 


Kind regards,
Ricky
the Telerik team
Browse the videos here>> to help you get started with JustMock
0
Aaron
Top achievements
Rank 1
answered on 16 Nov 2012, 04:42 PM
I have a similar scenario but need future mock constructors.  In the example provided in the post as the solution, the original constructor would still get called on the instantiation of the new LoginService().  In my case, there is some legacy code where I don't want the constructor to be called.  In fact, the true desired behavior is to return an object which I can specify so that anytime said object is created, it returns another mock object I specify.  It would be even more ideal if you could also vary by parameters and return different objects based on the constructor parameters similar to how you can with regular methods (Arg.IsAny....).  I can get away without that additional functionality for now (the vary by parameters) but am really trying to find a way to future mock constructors.  Is this possible?
0
Ricky
Telerik team
answered on 19 Nov 2012, 06:32 PM
Hi Araon,

I made a reply to your ticket # 630799 regarding this issue. Please check it out.

Kind Regards
Ricky
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Andrew
Top achievements
Rank 1
answered on 09 Jul 2014, 04:57 PM

This sounds like exactly what I need, but I am not able to get it to work. In my scenario. I am testing a method that creates a new object, and calls a method on that object. 

It's something similar to this scenario:

public SampleClass() {
    public int Number1 {get;set;}
    public int Number2 {get;set;}
  
    public int DoMath() {
        return Number1 + Number2;
    }
  
}

The code I'm testing would be similar to this:

public
int TestMethod() {
      var someModel = new SampleClass { Number1 = 2, Number2 = 3 };
      someModel.DoMath();
      // Other code
     return someNumber;
}


My TestMethod creates a new instance of SampleClass and the uses Mock.Arrange() to mock the DoMath() method, but it is not working.

Any advice?
My TestMethod creates a new instance of SampleClass and the uses Mock.Arrange() to mock the DoMath() method, but it is not working.Any advice?
0
Stefan
Telerik team
answered on 10 Jul 2014, 03:36 PM
Hello Andrew,

Can you give me the test method's code? I'd like to see what your arrangements and assertions look like. Also, can you explain how it's not working? Does it fail with an exception? Does it behave as if it weren't mocked at all?

Thank you for your patience.

Regards,
Stefan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Andrew
Top achievements
Rank 1
answered on 10 Jul 2014, 03:43 PM
It is behaving as if it is not mocked at all.  The method on the object I'm trying to mock makes a web service call, and I get an exception that the URL passed isn't invalid which makes sense, since in the test I wouldn't have the URL defined, but it shouldn't be trying at all.

Here's the Test Code:
// Arrange
var request = new CohesionRequest();
var calledCohesion = false;
Mock.Arrange(() => request.MakeCoreRequest(Arg.IsAny<string>(), Arg.IsAny<bool>()))
    .DoInstead(() => { calledCohesion = true; })
    .OccursOnce();
// Act
this.loanService.GetLoanTransferRecords("AP", "1234");
 // Assert
Assert.IsTrue(calledCohesion);
0
Stefan
Telerik team
answered on 11 Jul 2014, 07:53 AM
Hi Andrew,

Your arrangement as it is works only on the "request" instance. As I understand, the system under test creates and uses a different instance internally. For the arrangement to have an effect on all instances, you must add the .IgnoreInstance() clause, like so:
Mock.Arrange(() => request.MakeCoreRequest(Arg.IsAny<string>(), Arg.IsAny<bool>()))
    .IgnoreInstance()
    .DoInstead(() => { calledCohesion = true; })
    .OccursOnce();

Alternatively, you can use the following syntax:
Mock.Arrange(() => Arg.IsAny<CohesionRequest>().MakeCoreRequest(Arg.IsAny<string>(), Arg.IsAny<bool>()))
    .DoInstead(() => { calledCohesion = true; })
    .OccursOnce();
i.e. use Arg.IsAny<T> for the instance part of the arrangement, instead of a concrete instance.

When there's an arrangement that looks like it should work, but doesn't, you can debug it using the handy DebugView feature of JustMock.

Let me know if you're still having trouble.

Regards,
Stefan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Andrew
Top achievements
Rank 1
answered on 11 Jul 2014, 12:18 PM
Hi Stefan,

That worked, thank you so much.  I just have one clarifying question:  In Ricky's post at the top of this thread in response to the original question he didn't have to use IgnoreInstance or Mock using Arg.IsAny<>

I'm just curious what was different between the original question and my code that prevented the answer at the top from working for me.

Thanks again,
Andrew
0
Kaloyan
Telerik team
answered on 16 Jul 2014, 01:30 PM
Hi Andrew,

The initial reply from my colleague is rather old. Since then, there are changes that have been applied to the JustMock api.

Now, you can check this article from the online documentation in order to follow the correct guidelines about mocking future objects with JustMock. I hope it helps.

Regards,
Kaloyan
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
Tags
General Discussions
Asked by
Vincent
Top achievements
Rank 1
Answers by
Ricky
Telerik team
Vincent
Top achievements
Rank 1
Aaron
Top achievements
Rank 1
Andrew
Top achievements
Rank 1
Stefan
Telerik team
Kaloyan
Telerik team
Share this question
or