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

Mock.Assert Occurs failing

9 Answers 384 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
cori
Top achievements
Rank 1
cori asked on 28 Jul 2010, 09:36 PM
I'm probably doing something wrong here, but I can't figure out why Mock.Assert Occurs in my case isn't showing the mocked method called.  Here's the code, in brief:

Test code:
        [TestMethod]
      public void ProcessFilterResult_MailMessageDate_AfterLatestDBDate_ProcessesMessage_Test()
      {
            BounceHandler_Accessor target = new BounceHandler_Accessor();
            var data = Mock.Create<IDataAccess>();
            target._dal = data;
            Mock.Arrange( () => data.GetLatestEmailDate() ).Returns( DateTime.Now.AddDays( -7 ) );
            target._recordToDatabase = true;
 
            var result = Mock.Create<BounceFilterResult>();
 
            Cforge.Net.Mail.MailMessage msg = new Cforge.Net.Mail.MailMessage();
            msg.Date = new Cforge.Net.Mime.Headers.MailDateTime(DateTime.Now);
            msg.BodyText = @"X-ETC-MailingID: 00001
X-ETC-MailflowID: 10000";
 
            Mock.Arrange( () => result.MailMessage ).Returns( msg );
 
            target.ProcessFilterResult( result );
            Mock.Assert( () => data.RecordBouncedEmail( result, "00001", "10000" ), Occurs.Once() );
 
      }
the ProcessFilterResult checks some dates and a flag on the target, all of which pass. It uses some regex to find matches in the MailMessage.BodyText, which also match the asserted method call. Stepping through the code, I watch the result and data proxies match up to the Mocked objects and then watch the target._dal.RecordBouncedEmail() method call being called, but when I get back to the test code I still get the following exception. Telerik.JustMock.MockAssertionException was unhandled by user code
  Message=Expected call on the mock should be once, but it was called 0 time(s).
  Source=Telerik.JustMock Can anyone give me some idea what the problem might be?

9 Answers, 1 is accepted

Sort by
0
Ricky
Telerik team
answered on 29 Jul 2010, 09:22 AM
Hi cori,

Thanks for the issue. It turns out that Mock.Assert() is not working properly  for calls with mocked argument reference.  Currently, the workaround is to replace that argument with Arg.IsAny().

Therefore, please replace the following line:

Mock.Assert( () => data.RecordBouncedEmail( result, "00001", "10000" ), Occurs.Once() );

With the following line :

Mock.Assert( () => data.RecordBouncedEmail(Arg.IsAny<BounceFilterResult>(), "00001", "10000" ), Occurs.Once() );

The fix is queued for the next build.

Kind regards,
the Telerik team
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 Public Issue Tracking system and vote to affect the priority of the items
0
cori
Top achievements
Rank 1
answered on 29 Jul 2010, 11:56 AM
Huh.  I thought it might be something like that, but.....

I also tried the following:
  • added a Mock.Arrange for the data.RecordBouncedEmail call and then Assert against the data Mock:
    Mock.Arrange( () => data.RecordBouncedEmail( result, "00001""10000" ) ).Returns( 1 ).MustBeCalled();
    Mock.Assert( data );
  • Tried what the first response (seems to have been deleted now) indicated, using Any.String:
    Mock.Assert( () => data.RecordBouncedEmail( result, Arg.AnyString, Arg.AnyString ), Occurs.Once() );

In both of these cases the mock succeeds when I run the test in Debug, but fails with an Object Ref not set exception when I run without debugging.  They both fail on the target.ProcessFilterResult( result ); line.

I get the same error when using the code supplied below, but again it succeeds when running in debug, even when I just step over the offending line (i.e. I don't have to step into the RecordBouncedEmail method in debug mode for it to work).

The BounceFilterResult class is a fairly heavyweight class hat I don't control (one of the reasons I need to mock it), so I'm wondering if there's something in it that I'm not setting up in Mock.Arranges that is causing the error.

Here's the stack trace for that call - Line 128 is the ProcessFilterResult call after I wrapped it in a try/catch to try to glean some more information about what's happening:
Object reference not set to an instance of an object.
   at Microsoft.VisualStudio.TestTools.UnitTesting.Helper.ThrowInnerException(TargetInvocationException outer)
   at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.Invoke(String name, BindingFlags bindingFlags, Type[] parameterTypes, Object[] args, CultureInfo culture, Type[] typeArguments)
   at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.Invoke(String name, BindingFlags bindingFlags, Type[] parameterTypes, Object[] args, CultureInfo culture)
   at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.Invoke(String name, Type[] parameterTypes, Object[] args, CultureInfo culture)
   at Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.Invoke(String name, Type[] parameterTypes, Object[] args)
   at eMarketingEMailer.BounceHandler_Accessor.ProcessFilterResult(BounceFilterResult result)
   at eMarketingEMailerTests.BounceHandlerIntegrationTest.ProcessFilterResult_MailMessageDate_AfterLatestDBDate_ProcessesMessage_Test() in C:\Users\cschlege\Documents\Visual Studio 2010\Projects\eMarketingEMailer\eMarketingEMailerTests\BounceHandlerIntegrationTests.cs:line 128


When I run the test in debug mode the catch section isn't even run....
0
cori
Top achievements
Rank 1
answered on 29 Jul 2010, 01:46 PM
A little more detail.

I moved the try/catch I was using to try to collect information about what was going wrong during a non-debug-mode test run to inside the called method to see if I could uncover where the Object Ref not set exception was being generated.  Here's the resulting code:
private void ProcessFilterResult( BounceFilterResult result )
{
    try {
        if ( DateTime.Parse( result.MailMessage.Date.ToString() ) > lastRecordedBounceDate && _recordToDatabase ) {
 
            string mailingID = "";
            string mailFlowID = "";
            Regex mailingIDReg = new Regex( "X-ETC-MailingID: (.*)" );
            Match mailingIDMatch = mailingIDReg.Match( result.MailMessage.BodyText );
            if ( mailingIDMatch.Success ) {
                Group mailingIDGroup = mailingIDMatch.Groups[1];
                mailingID = mailingIDGroup.ToString();
            }
 
            Regex mailFlowIDReg = new Regex( "X-ETC-MailflowID: (.*)" );
            Match mailFlowIDMatch = mailFlowIDReg.Match( result.MailMessage.BodyText );
            if ( mailFlowIDMatch.Success ) {
                Group mailFlowIDGroup = mailFlowIDMatch.Groups[1];
                mailFlowID = mailFlowIDGroup.ToString();
            }
            _dal.RecordBouncedEmail( result, mailingID, mailFlowID );
        }
    } catch ( Exception ex ) {
        Debug.Print( ex.Message + Environment.NewLine + ex.StackTrace );
    }
}

What's really interesting (or annoying, depending on how you look at it) is that the exception is currently being thrown on the string mailingID = "";
line. I'm not at all sure why that would be happening at all, not least of all why it's happening in release mode but not in debug mode.
0
cori
Top achievements
Rank 1
answered on 29 Jul 2010, 01:55 PM
Aaaaand ... a little more detail:

I moved the assignment operation of those string vars from declaration to an else clause of the if statement that checks the result of the RegEx match, so those vars aren't assigned until later in the code. This makes the
Regex mailingIDReg = new Regex"X-ETC-MailingID: (.*)" );
line the first line that's doing any work, and now *that's* the line that throws the exception.

Also tried running the test in Debug mode but without any breakpoints set, so the code executes without me stepping through, and it passes under those conditions.

Not knowing the internals of JustMock at all, is it possible this is related to my passing a mocked parameter?
0
Ricky
Telerik team
answered on 29 Jul 2010, 02:16 PM

Hi cori,

Thanks for all those details and are pretty helpful. As your "result" class is mocked. This is where the problem is occurring. I was being able to replicate the issue just by mocking the argument and passing it into Mock.Assert().

Also there is an issue with loading type from multiple projects [mentioned in a different thread], so it looks like you have two issues in plate.  May be I can send you an internal build [through the email you have mentioned in telerik account], if you prefer.

Finally, one more question, when data.RecordBounceEmail is called , does it call the original method? . If not then definitely it's the issue with mocked argument.

Regards,
the Telerik team


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 Public Issue Tracking system and vote to affect the priority of the items
0
cori
Top achievements
Rank 1
answered on 29 Jul 2010, 02:27 PM
I would be happy to try an internal build, when you have it available. Email on my account would be fine

In response to your other query, no, the data.RecordBouncedEmail() call is not calling the original - that method interacts with the DB and I just want to make sure that the method gets called with the correct parameters.
0
Accepted
Ricky
Telerik team
answered on 29 Jul 2010, 04:29 PM

Hi cori,

As agreed, I just emailed you an internal build. Let me know if that solves your issue.


Regards,
the Telerik team


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 Public Issue Tracking system and vote to affect the priority of the items
0
cori
Top achievements
Rank 1
answered on 29 Jul 2010, 07:59 PM
Excellent, looks like it works great!

Only one test running so far, but the simple one that I couldn't complete is now passing

Not only that, but if I pass in the actual mocked result object instead of Arg.IsAny<BounceFilterResult>() it still passes.

Thanks for the quick fix!
0
Ricky
Telerik team
answered on 30 Jul 2010, 08:10 AM
Hello cori,

Great that things are working for you and have fun :-).


Regards,
the Telerik team
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 Public Issue Tracking system and vote to affect the priority of the items
Tags
General Discussions
Asked by
cori
Top achievements
Rank 1
Answers by
Ricky
Telerik team
cori
Top achievements
Rank 1
Share this question
or