Newbie: What's the problem in this code?

5 views
Skip to first unread message

hitechnical

unread,
Oct 22, 2009, 10:10:53 AM10/22/09
to Rhino.Mocks
Ok, I am starting on it now .. to try myself i wrote this code. What I
am trying to do here is, I've mocked User object on which i expect a
call from UserValidationService.IsValidUser method. Below is the code,

public class UserValidationService : IUserValidationService
{
public bool IsValidUser(IUser user)
{
if (String.IsNullOrEmpty(user.UserName) ||
String.IsNullOrEmpty(user.Password))
return false;
return true;
}
}

// The test code.

MockRepository mock = new MockRepository();

var validationService
= new UserValidationService();
var userToTest
= mock.CreateMock<IUser>(null);

Expect.On(userToTest).Call(userToTest.Name).Return
("Name");
Expect.On(userToTest).Call(userToTest.Password).Return
("Password");

mock.ReplayAll();
validationService.IsValidUser(userToTest);
mock.VerifyAll();

I get this error whenever VerifyAll is executed:
Rhino.Mocks.Exceptions.ExpectationViolationException:
IUser.get_UserName(); Expected #0, Actual #1.

Can someone enlight me?

Tim Barcz

unread,
Oct 22, 2009, 10:17:51 AM10/22/09
to rhino...@googlegroups.com
instead of CreateMock use DynamicMock...

it's the difference between strict and non mocks...favor non-strict (dynamic mocks)
--
Tim Barcz
Microsoft C# MVP
Microsoft ASPInsider
http://timbarcz.devlicio.us
http://www.twitter.com/timbarcz

hitechnical

unread,
Oct 22, 2009, 10:22:42 AM10/22/09
to Rhino.Mocks
Ok, I replaced Expect.On to SetupResult.For method and it worked fine.
Now, I am doing this --

SetupResult.For(userToTest.UserName).Return(new
System.Random(10).Next().ToString()).Repeat.Times(5);
SetupResult.For(userToTest.Password).Return("Password");

My expectation is to get 5 different random numbers each time I call
validationService.IsValidUser method

for(int i =1;i<=5;i++)
validationService.IsValidUser(userToTest);

Am I doing something silly?

Tim Barcz

unread,
Oct 22, 2009, 10:25:38 AM10/22/09
to rhino...@googlegroups.com
Did you change from mock.CreateMock<IUser> to mock.DynamicMock<IUser>?

bill richards

unread,
Oct 22, 2009, 3:33:24 PM10/22/09
to Rhino.Mocks
I'm not sure how the random number comes into play here ... what this
test does is upon accessing the UserName property a "random" number is
returned, instead of the actual name. So just to be certain are you
expecting this behaviour?

I also believe that since you are using the same seed value for
Random, each call will result in the same "random" (hence the quotes)
number being generated -I've been kown to be wrong before so pleasse
forgive me if my information with regards to Random is wrong (hence my
saying that I believe it to be the case, I guess I could test it out
before replying, but that would be too easy)

Now, if it is the case that a new random number is generated every
time, I still think you will not get the result you are looking for
because of the call to .Repeat.Times(5), because my understanding of
the functionality there is that the exact same call is expected to be
made five times.

It apears to me that the random numbers are only serving as five
different user names. Looking at the code you've supplied, it looks to
me as if you are trying to test whether the test passes when you run
it five times using five different user names, personally I would
write something like the follwing (using RhinoMock and nUnit) to
achieve that test, but really you only need to supply one names, since
after all it works for that, it will work for as many as you can throw
at it ...

[Test]
[TestCase("Name one")]
[TestCase("Name two")]
[TestCase("Name three")]
[TestCase("Name four")]
[TestCase("Name five")]
public void
WhenIsValidUserIsPassedAnIUserWithBothAUserNameAndPassword_ShouldReturnTrue
(string name)
{
var user = MockRepository.GenerateStub<IUSer>();
user.Stub(u=>u.UserName).Return(name);
user.Stub(u=>u.Password).Return(password);

var service = new UserValidationService();
var actual = service.IsValidUser(user);

Assert.That(actual, Is.True);
}

Or, are you expecting that when the call is made to IsValidUser, the
IUser interface implementation sets the UserName to a random number? -
if that's the case, I would seriously suggest changing the name of
your method, because this method only says to me that it is to be
called in order to test the validity of a user object.

Am I barking up completely the wrong tree?

hitechnical

unread,
Oct 26, 2009, 2:28:07 AM10/26/09
to Rhino.Mocks
Bill, you're completely correct. Thanks for your time to reply in much
detail. The idea was to understand how the Repeat.Times() calls the
enclosed statements (which is System.Random in this case), but as you
mentioned the seed will be same for every call, you are completely
right. In finance industry, we used to get such type of scenarios
where we need to pass in some random numbers as samples in order to
test the logic. How to achieve this sort of scenarios?

bill richards

unread,
Oct 26, 2009, 4:05:45 PM10/26/09
to Rhino.Mocks
Repeat.Times() does not make any calls, it is an expectation

imagine that the Random number generates the value 25. Your orignal
code then becomes

SetupResult.For(userToTest.UserName).Return("25").Repeat.Times(5);

which says that you are expecting userToTest.UserName to be called
five times and return the value "25" each time

your test will fail with the error

Rhino.Mocks.Exceptions.ExpectationViolationException:
IUser.get_UserName(); Expected #5, Actual #1.

As I mentioned in my previous post, to test the same method with
different sets of variables, I would use nUnit's TestCaseAttribute()
to pass in a range of values, I guess to use real random numbers you
might be able to do the following...

[TestCase(System.Random(DateTime.Now.Ticks).Next().ToString())]
[TestCase(System.Random(DateTime.Now.Ticks).Next().ToString())]
[TestCase(System.Random(DateTime.Now.Ticks).Next().ToString())]
[TestCase(System.Random(DateTime.Now.Ticks).Next().ToString())]
[TestCase(System.Random(DateTime.Now.Ticks).Next().ToString())]
WhenIsValidUserIsPassedAnIUserWithBothAUserNameAndPassword_ShouldReturnTrue
(string name)
{
const string password = "password";
var user = MockRepository.GenerateStub<IUSer>();
user.Stub(u=>u.UserName).Return(name);
user.Stub(u=>u.Password).Return(password);

var service = new UserValidationService();
var actual = service.IsValidUser(user);

Assert.That(actual, Is.True);
}


but all you are doing is creating a mock IUser implementation, setting
the value returned by UserName and then making sure that the mock is
valid (as prescribed by your business rule of "a user is valid if it
has a username and a password")

This test is testing that when presented with a valid IUser, does the
UserValidationService recognise it as a valid user, it should be
obvious that if the test passes with one properly instantiated IUser,
then it will pass with all, so only the first attempt is required. You
do however need to supply another unit test to ensure that when the
service is passed an incorrectly instantiated IUser that the call to
IsValid does not return true.

Vadivel Kumar

unread,
Oct 27, 2009, 10:09:12 AM10/27/09
to rhino...@googlegroups.com
Excellent. Thanks
Reply all
Reply to author
Forward
0 new messages