I have been evaluating Rhino.Mocks for some weeks, and I think it is
great!
However, I got a question yesterday, please refer to the sample below.
public class Obj
{
public Obj() { }
public BeingTested
{
Init();
}
private void Init( )
{ // do something internal
}
}
[TestMethod()]
public void TestContructor()
{
MockRepository _mocks = new MockRepository();
Obj obj = (Obj)_mocks.CreateMock<Obj>();
obj.Init()) // *** compilation error, since Init is private, how
can I tell this is expected to be called?
_mocks.ReplayAll();
obj.BeingTested();
_mocks.VerifyAll();
}
Any help would be grateful! Thanks in advance.
Thanks for your help !
On Nov 29, 2:54 pm, "Ayende Rahien" <aye...@ayende.com> wrote:
> You can't mock private (or non-virtual) methods.
>
> > Any help would be grateful! Thanks in advance.- Hide quoted text -- Show quoted text -
So, according to the example, when using Rhino.Mocks , how can I verify
Also, I'd say that if you are testing a public method that happens to
call private methods within the same class then you don't need to use
mocks because the private method is still in the class under test (CUT).
It is only when the code calls something outside the CUT that mocks
should be used. (Well, in my opinion anyway)
______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email
______________________________________________________________________
Privileged/Confidential information may be contained in this email and is intended for the use of the addressee only.
If you are not the addressee, you may not copy or otherwise use the information.
If you receive this email by mistake, please notify us immediately at: in...@letsure.co.uk
Although this message and any attachments are believed to be free of any virus or other defect that might affect any computer system into which it is received and opened, it is the responsibility of the recipient to ensure that it is virus-free and no responsibility is accepted by either Lumley Letsure Limited (Letsure) or Lumley Limited for any loss or damage in any way arising from its use.
Lumley Letsure Limited Registered in England No. 03010153
Registered Office: Hargrave House Belmont Road Maidenhead Berkshire SL6 6TB
Lumley Letsure Limited is authorised and regulated by the Financial Services Authority. Registration number is 313817.
Lumley Limited Registered in England No. 00378519
Registered Office: Hargrave House Belmont Road Maidenhead Berkshire SL6 6TB
Lumley Limited is authorised and regulated by the Financial Services Authority. Registration number is 314040.
So, according to the example, when using Rhino.Mocks , how can I verify
Sorry that I missed some code in my first post, please find what I want
to ask below
public class Obj
{
public Obj() { }
public BeingTested
{
Init();
}
private void Init( )
{ // do something internal
}
}
[TestClass()]
public class ObjTest
{
[TestMethod()]
public void TestContructor()
{
MockRepository _mocks = new MockRepository();
Obj obj = (Obj)_mocks.CreateMock<Obj>();
obj.Init()) // *** compilation error, since Init is private,
how can I tell this is expected to be called?
_mocks.ReplayAll();
obj.BeingTested();
_mocks.VerifyAll();
}
}
Actually, what I want to test is the BeingTested method of the class
Obj, which depends on its private method Init().
As you said that the CUT should not be mocked, may I know the reason
behind it? Since I am still a newbie on unit testing, and going to
learn whatever it need.
Thanks for your help.
If your BeingTested method (which needs parenthesis by the way, unless
it is actually property but missing the get/set) calls an internal
method in the CUT. Since the method is private, I'd normally have that
as part of the test of the public method because it is not outside the
class. The only things I mock are other objects that the CUT calls.
VSTS, which I notice you are using, does do some nice code generation to
allow you to unit test private methods on their own through a special
"Accessor" class, so you can test the workings on the private method in
its own unit test as well.
I'd rewrite your test method as follows:
[TestClass()]
public class ObjTest
{
[TestMethod()]
public void TestContructor()
{
// Set up the environment for the test
MockRepository _mocks = new MockRepository();
Obj obj = new Obj(); // Note this is a real Obj
// ***
// If Init() calls anything outside the class under test
// then set up those mocks here
// ***
// Perform the test
_mocks.ReplayAll();
obj.BeingTested(); // Will call the real Init() method
// Check that the test worked. Add any Asserts necessary
_mocks.VerifyAll();
}
}
-----Original Message-----
From: Rhino...@googlegroups.com [mailto:Rhino...@googlegroups.com]
On Behalf Of Tony Cheung
Sent: 29 November 2006 13:49
To: Rhino.Mocks
Subject: Re: How to mock private method?
Thanks for your reply!
public BeingTested
{
Init();
}
}
[TestClass()]
public class ObjTest
{
obj.BeingTested();
_mocks.VerifyAll();
}
}
Thanks for your help.
______________________________________________________________________
This email has been scanned by the MessageLabs Email Security System.
For more information please visit http://www.messagelabs.com/email
______________________________________________________________________
Privileged/Confidential information may be contained in this email and is intended for the use of the addressee only.
You could make the Init a virtual protected method - Then RhinoMocks
could replace the Init() with its own mockable version.
public class Obj
{
public Obj() { }
public BeingTested
{
Init();
}
// No longer private:
protected virtual void Init( )
{ // do something internal
}
}
Of course, this changes the CUT slightly so that any class you derive
will have access to the Init() method (something it previously wouldn't
have access to) and you make the class sealed.
-----Original Message-----
From: Rhino...@googlegroups.com [mailto:Rhino...@googlegroups.com]
On Behalf Of Tony Cheung
Sent: 29 November 2006 13:49
To: Rhino.Mocks
Subject: Re: How to mock private method?
Thanks for your reply!
public BeingTested
{
Init();
}
}
[TestClass()]
public class ObjTest
{
obj.BeingTested();
_mocks.VerifyAll();
}
}
Thanks for your help.
Of course, this changes the CUT slightly so that any class you derive
will have access to the Init() method (something it previously wouldn't
have access to) and you **can't** make the class sealed.
public BeingTested
{
Init();
}
Thanks for your reply!
public BeingTested
{
Init();
}
}
[TestClass()]
public class ObjTest
{
obj.BeingTested();
_mocks.VerifyAll();
}
}
Thanks for your help.
Privileged/Confidential information may be contained in this email and is intended for the use of the addressee only.
I just come up with another question. Instead of a private method, it
is now calling a static method from other class, eg.
// Sign enum
public enum Sign
{ Positive, Negative, Neutral }
// CUT
public class Obj
{
public Obj() { }
public void BeingTested(int condition)
{
if (condition > 0)
SignHelpers.DoSomethingPositive(this);
else if (condition < 0)
SignHelpers.DoSomethingNegative(this);
else
SignHelpers.DoNothing(this);
}
private Sign _sign;
public Sign Sign
{
get { return _sign; }
set { _sign = value; }
}
}
// Helper class provide static helper routines
public class SignHelpers
{
private SignHelpers() { }
public static void DoSomethingPositive(Obj obj)
{
obj.Sign = Sign.Positive;
}
public static void DoSomethingNegative(Obj obj)
{
obj.Sign = Sign.Negative;
}
public static void DoNothing(Obj obj)
{
obj.Sign = Sign.Neutral;
}
}
In this case, if I want to test Obj's BeingTested method, how should I
setup the mocks?
[TestClass()]
public class ObjTest
{
[TestMethod()]
public void PositiveTest()
{
int condition = 10;
MockRepository _mocks = new MockRepository();
Obj obj = new Obj();
//
// *** how should I setup the mocks so that SignHelper's
DoSomethingPositive has
// *** to be called, but not DoSomethingNegative and DoNothing
??
//
// Helpers.DoSomethingPositive(obj); <-- I cannot do this,
since it will make the real call
_mocks.ReplayAll();
obj.BeingTested(condition);
_mocks.VerifyAll();
Assert.AreEqual(Sign.Positive, obj.Sign);
}
}
Thanks for any comments!
- Tony
> For more information please visithttp://www.messagelabs.com/email
> ______________________________________________________________________
>
> Privileged/Confidential information may be contained in this email and is intended for the use of the addressee only.
>
> If you are not the addressee, you may not copy or otherwise use the information.
>
> If you receive this email by mistake, please notify us immediately at: i...@letsure.co.uk
>
> Although this message and any attachments are believed to be free of any virus or other defect that might affect any computer system into which it is received and opened, it is the responsibility of the recipient to ensure that it is virus-free and no responsibility is accepted by either Lumley Letsure Limited (Letsure) or Lumley Limited for any loss or damage in any way arising from its use.
>
> Lumley Letsure Limited Registered in England No. 03010153
> Registered Office: Hargrave House Belmont Road Maidenhead Berkshire SL6 6TB
> Lumley Letsure Limited is authorised and regulated by the Financial Services Authority. Registration number is 313817.
>
> Lumley Limited Registered in England No. 00378519
> Registered Office: Hargrave House Belmont Road Maidenhead Berkshire SL6 6TB
> Lumley Limited is authorised and regulated by the Financial Services Authority. Registration number is 314040.- Hide quoted text -- Show quoted text -
Check this out for a reasonable perspective on testing:
http://behaviour-driven.org/