chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
I would like to test a subsystem with multiple threads, such that I can write statements like

mockObject.expectMethodCall("methodName", timeout);

such that if it times out, it throws an exception failing my test, or if the method is called within the timeout, it will pass back the parameters that were passed into the "methodName" parameter. Can I use TypeMock to test this system? MockLib in Java is one example that does this in Java.
thanks,
dean
asked by deanhiller (1.3k points)

9 Answers

0 votes
Hi Dean,
TypeMock does not support this yet, I can add this to our feature requests.

MockLib in Java is one example that does this in Java.


Can you give me a pointer to MockLib or explain the exact behaviour as I don't fully understand what is supposed to happen.
answered by richard (3.9k points)
0 votes
whoops, for some reason my reply started a new thread. I most of messed up. Please see new thread for answers.
answered by deanhiller (1.3k points)
0 votes
Hi,
I have quoted from new thread:
(sorry, forgot to click notify me when a reply is posted). I would love to help add code on this feature!!!!

Here are some examples in Java
http://mockobject.sourceforge.net/

Basically, there is no Init, there is not verify. Instead, there is just code like this

CalledMethod m = mockObj.expectCall("method");

assertTrue("values should be same", true, m.getParameters()[0]);
assertTrue("values should be same", 5, m.getParameters()[1]);

The expectCall blocks for a period of "timeout" which is configured by the user. The default is 10 seconds and I have never overridden it myself. Realize the return values can't be specified in the expectCall as the method may be called before or after my call to expectCall, so instead there are methods to add return values and add throwing exceptions. It is quite nice not needing a verify or init. This allows one to get rid of it.

thanks,
dean


Thanks for the pointers, this looks very interesting, but there are a few differences in the frameworks.
:arrow: TypeMock mocks REAL concrete classes and not only interfaces.
:arrow: We require Init() to be called for two reasons. The first is to start the insertion system, and the second is to clear all return values of previous tests, so if a test fails, we don't fail the whole suite. This can happen in the proposed framework
:arrow: Verify() is actually used to validate that all expected calls were made, so if we expect that "method" should be called twice, but it was called only once, we can fail the test (You don't have to call Verify(), but I recommend it). This is something that cannot be done with the shown framework

:idea: You could implement this using the call event feature or using the dynamic return value delegate , although you will still have to write your expectations before the calling method, and the validations will be in another method, which can make things a little hard to understand

:?: Perhaps adding the following API's to the mock can help:
// save arguments for all calls
mock.SaveArguments = true
// get the arguments sent to method when called the <callNumber> time
mock.SentArguments("method",callNumber)

Then we our test will look like this:
[Test] 
public void OurTest()
{
      Authentication authenticator = new Authentication();
      MockManager.Init ();
      // the Logger class is now being mocked
      Mock logMock = MockManager.Mock(typeof(Logger)); 
       // save all arguments
      logMock.SaveArguments = true;
     
      // run test 
      authenticator.IsAuthenticated("user","password");      

      // Validate arguments sent to Log the first time
      Assert.AreEqual(true,logMock.SentArguments("Log",1)[0]);
      Assert.AreEqual(5,logMock.SentArguments("Log",1)[1]);
      // we don't really need to test if Log was actually called
      // because test will fail on previous line if Log wasn't called
      //MockManager.Verify();
} 

But adding this might confuse developers, as they will have too many choises to validate the calls.

Of course it seems easier to do the following: (Notice the Args())
[Test] 
public void OurTest()
{
      Authentication authenticator = new Authentication();
      MockManager.Init ();
      // the Logger class is now being mocked
      Mock logMock = MockManager.Mock(typeof(Logger)); 
       // set up our expectations 
      logMock.ExpectCall("Log").Args(true,5);
     
      // run test 
      authenticator.IsAuthenticated("user","password");      
      // make sure Log was actually called
      MockManager.Verify();
} 


About the timeout, we could probrably add a
mock.Timeout = timeout;


What do you think?
answered by richard (3.9k points)
0 votes
First, thanks for the great detailed reply!!!! It is really appreciated.

Actually, mocklib has all but one of those features you mention, but just done differently.......Before I go into that(you can skip to the bottom for my explanations after), I would like to understand more about the code you wrote.

I have a question on this code.....

// run test
authenticator.IsAuthenticated("user","password");

// Validate arguments sent to Log the first time
Assert.AreEqual(true,logMock.SentArguments("Log",1)[0]);

1. Let's say authenticator is called and drops that on another thread, and returns. The logMock.SentArguments is executed but no method on logMock has been called yet because the other thread hasn't finished just yet. Is logMock.SentArguments going to block and then released when logMock is finally called? In most telecom code, I see sleeps in the test cases which slows down the testing in the autobuilds ALOT. With mocklib, sleeps were avoided.

This happening is not too common on the non-telecom projects I have worked on, but of all the telecom projects I worked on, it can be very very common.

Explanations of features of mocklib........

* Arrow TypeMock mocks REAL concrete classes and not only interfaces.
Yes, mocklib uses jdk's proxy which doesn't mock objects unfortunately which is sad(I agree). It could use a bytecode lib to rememedy that if they want.

* Arrow We require Init() to be called for two reasons. The first is to start the insertion system, and the second is to clear all return values of previous tests, so if a test fails, we don't fail the whole suite. This can happen in the proposed framework

Actually, depends. It only happens if I use the same mockobject for every test. Usually people leverage setup/teardown to recreate a bunch of mockobjects. (ie. I think this is the users responsibility and while Init may be in Setup method, I typically have used mocklib to create a brand new mockobject that had nothing to do with the previous). sometimes this was two mockobjects if I needed like two ActionListeners.

Arrow Verify() is actually used to validate that all expected calls were made, so if we expect that "method" should be called twice, but it was called only once, we can fail the test (You don't have to call Verify(), but I recommend it). This is something that cannot be done with the shown framework

Actually, this is also done with mocklib. At the end of a test, there is a special static field such that you call mockObj.expectCall(MockObject.NONE). Also, when you call expectCall("methodName"), it will fail if other methods were called. There are other methods like expectCalls() which accepts an array of method names to be called.
answered by deanhiller (1.3k points)
0 votes
First, thanks for the great detailed reply!!!! It is really appreciated.

Your welcome.

1. Let's say authenticator is called and drops that on another thread, and returns. The logMock.SentArguments is executed but no method on logMock has been called yet because the other thread hasn't finished just yet. Is logMock.SentArguments going to block and then released when logMock is finally called? In most telecom code, I see sleeps in the test cases which slows down the testing in the autobuilds ALOT. With mocklib, sleeps were avoided.

This happening is not too common on the non-telecom projects I have worked on, but of all the telecom projects I worked on, it can be very very common.

Well, I think that I am getting the picture now. It seems that mocklib is a very simple framework, although it would be more natural for TypeMock to have something in the following manner:
Note the VerifyWithTimeout
[Test] 
public void OurTest() 
{ 
      Authentication authenticator = new Authentication(); 
      MockManager.Init (); 
      // the Logger class is now being mocked 
      Mock logMock = MockManager.Mock(typeof(Logger)); 
       // set up our expectations 
      logMock.ExpectCall("Log").Args(true,5); 
      
      // run test (This uses another thread)
      authenticator.IsAuthenticated("user","password");  
      // block and make sure Log was actually called with correct args
      MockManager.VerifyWithTimeout(milliseconds);
} 

This will probrably solve your case, and will allow:
:idea: Mocking All instances of a type. Not only one instance.
:idea: Mock a future instance of a type. (a new somewhere in our tested code) even though it is not passed as a parameter (Notice that logMock is never passed to authenticator)
:idea: Allow to return ref and out parameters (doesn't exist in Java)
:idea: Support future versions where we are going to introduce conditional expectations that are mocked, depending on the input arguments, and support swapping arguments for complex types (More on this in our next release)
:idea: Support future versions where we will introduce labeling expecations so that they can be modified dynamicly (More on this in our next release)

We would also have to verify the arguments when VerifyWithTimeout() is called or else the failure will be lost in the other thread, the same applies to code surrounded by a try/catch (Exception)

What do you think about this? I will see if I can add this requirment.
answered by richard (3.9k points)
0 votes
sweeet. that would be much better. There are some other things to consider though....You have to be able to add exceptions(and queue them up) as well as return values like so

mockObj.addReturnValue("methodName", objectToReturn);

which has to be done before the authenticator.IsAuthenticated() call.

There are some things you said that make me nervous though....Questions inline.

Idea Mocking All instances of a type. Not only one instance.


really, you can't do all instances of a type right now...i have encountered this a few times already where I wanted one listener to throw an exception back to the system and another to see if it received the event.

Idea Mock a future instance of a type. (a new somewhere in our tested code) even though it is not passed as a parameter (Notice that logMock is never passed to authenticator)


This can be very useful for legacy systems, but I am not sure I like this for new systems. Part of the nice thing about TDD is that it results in better design, and this seems to avoid that.

Idea Allow to return ref and out parameters (doesn't exist in Java)


Yeah, this rocks about your lib!

Idea Support future versions where we are going to introduce conditional expectations that are mocked, depending on the input arguments, and support swapping arguments for complex types (More on this in our next release)


I assume this plays with the ref and out return values which would be nice.

thanks for the discussion.
answered by deanhiller (1.3k points)
0 votes
Hi,
Here are some answers.
mockObj.addReturnValue("methodName", objectToReturn);
which has to be done before the authenticator.IsAuthenticated() call.

This will be done as follows:
logMock.ExpectAndReturn("GetSomething",objectToReturn).Args(true,5);

Mocking All instances of a type. Not only one instance.

really, you can't do all instances of a type right now...i have encountered this a few times already where I wanted one listener to throw an exception back to the system and another to see if it received the event.

This is very usfull is cases where you want to mock types that might already be instanciated (Singlton), or if you want all instances to behave the same.

Mock a future instance of a type. (a new somewhere in our tested code) even though it is not passed as a parameter (Notice that logMock is never passed to authenticator)

This can be very useful for legacy systems, but I am not sure I like this for new systems. Part of the nice thing about TDD is that it results in better design, and this seems to avoid that.

This is more of a religious debate, but at least you have a choise, if you want to have a 'new' in your code, and not need to pass an interface up the call heirachy, which can create a dependancy that was never really needed. see an article that I found on the web Mock objects done right
answered by richard (3.9k points)
0 votes
interesting. Yes, i kind of do like the ability to handle new....I am tempted to include it in java's mocklib, but have not decided yet. i can't seem to read the article due to company blocking that site for some reason. I will read it later from home.

thanks for all the answers....the solution looks good, and you gave me some ideas of what I would like to add to java's mocklib.
answered by deanhiller (1.3k points)
0 votes
Hi,
TypeMock 2.3 Supports Multiple Threads,
Please refer to documentation for more information
answered by scott (32k points)
...