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

Mock property

8 Answers 126 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Michel Corbin
Top achievements
Rank 1
Michel Corbin asked on 29 Dec 2010, 04:13 PM
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.

8 Answers, 1 is accepted

Sort by
0
Accepted
Ricky
Telerik team
answered on 31 Dec 2010, 08:41 AM
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
0
Michel Corbin
Top achievements
Rank 1
answered on 31 Dec 2010, 03:55 PM
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
0
Ricky
Telerik team
answered on 03 Jan 2011, 12:38 PM
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
0
Michel Corbin
Top achievements
Rank 1
answered on 03 Jan 2011, 07:45 PM
With your last suggestion, it doesn't work.


0
Michel Corbin
Top achievements
Rank 1
answered on 05 Jan 2011, 08:38 PM
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.
0
Ricky
Telerik team
answered on 06 Jan 2011, 04:35 PM
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
0
Michel Corbin
Top achievements
Rank 1
answered on 07 Jan 2011, 05:17 AM
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.
0
Ricky
Telerik team
answered on 07 Jan 2011, 11:04 AM
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
Tags
General Discussions
Asked by
Michel Corbin
Top achievements
Rank 1
Answers by
Ricky
Telerik team
Michel Corbin
Top achievements
Rank 1
Share this question
or