Mock property

9 posts, 1 answers
  1. Michel Corbin
    Michel Corbin avatar
    20 posts
    Member since:
    Apr 2010

    Posted 29 Dec 2010 Link to this post

    Hi,

    Yesterday, I tried to mock a property of an object to define the return value but it doesn't work. I know that I am two levels depth but can you explain me what is wrong with this code...

    Public Interface IProcessor
       Property Connection As IConnection
       Function Execute() As Boolean
    End Interface
     
    Public Interface IConnection
       Function Open() As Boolean
    End Interface
     
    Public Class DatabaseExecutor
       Implements IProcessor
     
       Public Property Connection As IConnection Implements IProcessor.Connection
     
       Public Function Execute() As Boolean Implements IProcessor.Execute
          If Me.Connection.Open Then
             Return True
          Else
             Return False
          End If
       End Function
    End Class
     
    Imports NUnit.Framework
    Imports Telerik.JustMock
     
    <TestFixture()>
    Public Class DatabaseExecutorTests
       ''' <summary>
       ''' This test fail because I try to mock the function open of the objet IConnection directly
       ''' from the property Connection of the object Processor.
       ''' </summary>
       ''' <remarks></remarks>
       <Test()>
       Public Sub Execute_SimpleRequest_ReturnsTrue()
          Dim executor As New DatabaseExecutor
     
          executor.Connection = Mock.Create(Of IConnection)()
     
          Mock.Arrange(Function() executor.Connection.Open).Returns(True)
     
          Assert.AreEqual(True, executor.Execute)
       End Sub
     
       ''' <summary>
       ''' This test pass because I create the connection separatly of the Processor objet and then
       ''' assign it to the property Processor.
       ''' </summary>
       ''' <remarks></remarks>
       <Test()>
       Public Sub Execute_SimpleRequestViaProperty_ReturnsTrue()
          Dim executor As New DatabaseExecutor
          Dim connection As IConnection = Mock.Create(Of IConnection)()
     
          Mock.Arrange(Function() connection.Open).Returns(True)
     
          executor.Connection = connection
     
          Assert.AreEqual(True, executor.Execute)
       End Sub
    End Class

    If you want, I can send you a demo but I think this will be very easy question for you.
  2. Answer
    Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 31 Dec 2010 Link to this post

    Hi Samuel,

    Thanks for sending the issue. In case of mocking nested property, it is an extra step to create the mock of that nested property first and then use it Mock.Arrange. For your example instead doing the following:

    <TestMethod()>
    Public Sub Execute_SimpleRequest_ReturnsTrue()
        Dim executor As New DatabaseExecutor
        executor.Connection = Mock.Create(Of IConnection)()
        Mock.Arrange(Function() executor.Connection.Open).Returns(True)
        Assert.AreEqual(True, executor.Execute)
    End Sub

    You can write the test in the following way:

    <TestMethod()>
    Public Sub Execute_SimpleRequest_ReturnsTrue()
        Dim executor As New DatabaseExecutor
        Mock.Arrange(Function() executor.Connection.Open).Returns(True)
        Assert.AreEqual(True, executor.Execute)
    End Sub

    However, in regard to the first sample, it should work as expected where you are manually creating the mock for the nested property. I am going add that to the product log as an issue.


    Thanks again for using JustMock and reporting the issue.

    Kind Regards,
    Ricky
    the Telerik team

    Browse the videos here>> to help you get started with JustMock
  3. DevCraft R3 2016 release webinar banner
  4. Michel Corbin
    Michel Corbin avatar
    20 posts
    Member since:
    Apr 2010

    Posted 31 Dec 2010 Link to this post

    Thank you for the answer.

    Can you tell me when you think this bug will be corrected.

    I ask you that because the workaround of creating the property object independently for dozens of tests (could be hundreds...) is not very great especially is after creating this ton of code, you will add a fix.

    Thank you
  5. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 03 Jan 2011 Link to this post

    Hi Samuel,

    Thanks again for sending the issue. Regarding the mocking of nested property I would recommend (preferred way as well) you to arrange it in the following way (directly using the get accessor):

    <TestMethod()> 
    Public Sub Execute_SimpleRequest_ReturnsTrue() 
        Dim executor As New DatabaseExecutor 
        Mock.Arrange(Function() executor.Connection.Open).Returns(True) 
        Assert.AreEqual(True, executor.Execute) 
    End Sub

    However in the coming release (Q1), you would also be able to do this: 

    Dim executor As New DatabaseExecutor 
    executor.Connection = Mock.Create(Of IConnection)() 
    Mock.Arrange(Function() executor.Connection.Open).Returns(True) 

    But this actually makes the test more verbose and in that regard the first one could be much more elegant.

    Moreover, I entered a PITS issue for it. You can further track it here:
    http://www.telerik.com/support/pits.aspx#/public/justmock/4500

    Kind Regards,
    Ricky
    the Telerik team
    Browse the videos here>> to help you get started with JustMock
  6. Michel Corbin
    Michel Corbin avatar
    20 posts
    Member since:
    Apr 2010

    Posted 03 Jan 2011 Link to this post

    With your last suggestion, it doesn't work.


  7. Michel Corbin
    Michel Corbin avatar
    20 posts
    Member since:
    Apr 2010

    Posted 05 Jan 2011 Link to this post

    I think the sample code that you have provide don't work with the free edition.

    <TestMethod()>
    Public Sub Execute_SimpleRequest_ReturnsTrue()
        Dim executor As New DatabaseExecutor
        Mock.Arrange(Function() executor.Connection.Open).Returns(True)
        Assert.AreEqual(True, executor.Execute)
    End Sub

    When I do this, the method Execute throw an exception because the object Connection is at nothing. But if I create an object connection, assign it to the executor.Connection and then use this object to Arrange the return of Open, it work.

    <TestMethod()>
    Public Sub Execute_SimpleRequest_ReturnsTrue()
       Dim executor As New DatabaseExecutor
       Dim connection As IConnectionFactory
     
       connection = executor.Connection
     
       Mock.Arrange(Function() connection.Open).Returns(True)
     
       Assert.AreEqual(True, executor.Execute)
    End Sub

    Is this because of free edition or that I don't understand what you said or that what you said is wrong?

    Thank you.
  8. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 06 Jan 2011 Link to this post

    Hi Samuel,

    Thanks again for making the post.

    The following test won’t pass in the free version as DatabaseExecutor.Connection is a final property or requires profiler to intercept and as free version is based on proxy (works like Moq, Rhino, etc).

    <TestMethod()> 
    Public Sub Execute_SimpleRequest_ReturnsTrue() 
        Dim executor As New DatabaseExecutor 
        Mock.Arrange(Function() executor.Connection.Open).Returns(True) 
        Assert.AreEqual(True, executor.Execute) 
    End Sub

    I have attached a test project with your provided classes from previous post. Please take a look at different cases (the one which passes and the ones which fail).

    Using the free version, the following test will pass:

    <TestMethod()>
    Public Sub Execute_SimpleRequest_ReturnsTrue()
        Dim executor As New DatabaseExecutor
        Dim connection = Mock.Create(Of IConnection)()
        executor.Connection = connection
        Mock.Arrange(Function() connection.Open).Returns(True)
        Assert.AreEqual(True, executor.Execute)
    End Sub

    However, if you try to create the Connection object manually it will fail as like the first one since partial mocking requires profiler:

    <TestMethod()>
    Public Sub Execute_SimpleRequest_ReturnsTrue_ManualObject()
        Dim executor As New DatabaseExecutor
        Dim connection As New Connection
        executor.Connection = connection
        Mock.Arrange(Function() connection.Open).Returns(True)
        Assert.AreEqual(True, executor.Execute)
    End Sub


    Finally, to make it more user friendly I am adding a task to throw proper exception in free version for mocking members that requires profiler.

    You can track the status of the task at :
    http://www.telerik.com/support/pits.aspx#/public/justmock/4550


    Please do feel free to write back for any further questions.


    Kind Regards,
    Ricky
    the Telerik team
    Browse the videos here>> to help you get started with JustMock
  9. Michel Corbin
    Michel Corbin avatar
    20 posts
    Member since:
    Apr 2010

    Posted 06 Jan 2011 Link to this post

    Hi,

    I tried the demo that you provide and when I try to run each test independently, it works but if I try to run all test in one batch, the function Execute_SimpleRequest_ReturnsTrue_Nested fails. For execute theses tests, I use your trial version that have a profiler.

    I change the unit test engine for Nunit and I run it with Resharper.

    Do you know if the last test fails when it run on batch on your side or if it is a combination of Nunit, Resharper and JustMock.

    Thank you again for your great support.
  10. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 07 Jan 2011 Link to this post

    Hi Samuel,

    Thanks again for making the post. In regard to your trial issue, MSTest runs the tests in the following sequence:

    Execute_SimpleRequest_ReturnsTrue_Nested
    Execute_SimpleRequest_ReturnsTrue
    Execute_SimpleRequest_ReturnsTrue_ManualObject

    Therefore, all the test passes. Here, Execute_SimpleRequest_ReturnsTrue runs second therefore do not interfere with the profiler initialization.

    But in other cases like running with ReSharper Test Runner or TestDriven.Net, tests run in the order as the methods are defined. Therefore, in this case the execution flow is:

    Execute_SimpleRequest_ReturnsTrue
    Execute_SimpleRequest_ReturnsTrue_Nested
    Execute_SimpleRequest_ReturnsTrue_ManualObject

    So, here in the first test Connection property gets complied(.net Framework fires OnJitCompilationStarted) through this line.

    executor.Connection = connection

    As a result, _ReturnsTrue_Nested fails as profiler fails to intercept it. The solution is that you pre-initialize the property to avoid this kind of ordering issues.

    Therefore, I added the following method in the test class and everything worked as expected.


    <TestInitialize()>
    Public Sub TestInit()
        Mock.Partial(Of DatabaseExecutor).For(Function(x) x.Connection)
    End Sub


    I am re-attaching the project with this update. Please take a look at it and also do feel free to write back for any exceptions.


    Kind Regards,
    Ricky
    the Telerik team
    Browse the videos here>> to help you get started with JustMock
Back to Top
DevCraft R3 2016 release webinar banner