Ayende @ Rahien

Oren Eini aka Ayende Rahien CEO of Hibernating Rhinos LTD, which develops RavenDB, a NoSQL Open Source Document Database.

You can reach me by:

oren@ravendb.net

+972 52-548-6969

Posts: 7,116 | Comments: 49,943

filter by tags archive
time to read 1 min | 170 words

There has been an invaluable amount of discussion regarding the question I pose about the API design of Rhino Mocks 3.5. Jeremy Gray in particular has been helpful in making good suggestions and making the argument to simplify the API for developers who are not experts in TDD terminology and usage.

My current thinking is to combine GenerateMock() and GenerateStub() into a single method, GenerateTestDouble(). This method will return a dynamic mock.

If you want a true stub, you will be able to call myTestDouble.StubUnexpectedInteractions(). Note, since stubs have a special behavior for properties, I am also considering: myTestDouble.StubPropertiesAndUnexpectedInteractions(); .

If you want a strict mock, you will be able to call myTestDouble.FailOnUnexpectedInteractions();

Partial mock will not be supported by the static GenerateTestDouble method, and will require using the usual instance methods.

Calling VerifyAllExpectations() will be supported on all mocks.

The only remaining open question is whatever calling Expect() on an object that you previously called StubUnexpectedInteractions() should fail or not.

Thoughts?

time to read 2 min | 235 words

Let us say that we have the following code that we want to test:

public void ForgotMyPassword(string username)
{
   var user = users.GetUserByName(username);
   user.HashedPassword = "new pass";
   users.Save(user);
}

One way to write the test is:

public void When_user_forgot_password_should_save_user()
{
    var mockUserRepository = MockRepository.GenerateMock<IUserRepository>();
    var stubbedSmsSender = MockRepository.GenerateStub<ISmsSender>();

    var theUser = new User{HashedPassword = "this is not hashed password"};    

    mockUserRepository.Stub(x => x.GetUserByName("ayende")).Return(theUser);

    mockUserRepository.Expect( x => x.Save(theUser) );

    var controllerUnderTest = new LoginController(mockUserRepository, stubbedSmsSender);

    controllerUnderTest.ForgotMyPassword("ayende");

    mockUserRepository.VerifyAllExpectations();
}

Another would be:

public void When_user_forgot_password_should_reset_password()
{
    var stubUserRepository = MockRepository.GenerateStub<IUserRepository>();
    var stubbedSmsSender = MockRepository.GenerateStub<ISmsSender>();

    var theUser = new User{HashedPassword = "this is not hashed password"};    

    stubUserRepository.Stub(x => x.GetUserByName("ayende")).Return(theUser);

    var controllerUnderTest = new LoginController(mockUserRepository, stubbedSmsSender);

    controllerUnderTest.ForgotMyPassword("ayende");

    stubUserRepository.AssertWasCalled( x => x.Save(user));
}

Again, we have the question of should we even allow asserts on stubs. But beyond that, consider this two tests, both are functionally the same. Thoughts?

time to read 1 min | 51 words

Here is an interesting problem. What should this piece of code do?

var stubSmsSender = MockRepository.GenerateStub<ISmsSender>();
// test code
stubSmsSender.VerifyAllExpectations();

Right now this is a no-op.

But since stubs are explicitly not mocks, they shouldn't be verified. Should I throw here? For something which is a test design decision?

FUTURE POSTS

  1. Building a social media platform without going bankrupt: Part I–Laying the numbers - about one hour from now
  2. Building a social media platform without going bankrupt: Part II–Accepting posts - about one day from now
  3. Building a social media platform without going bankrupt: Part III–Reading posts - 2 days from now
  4. Building a social media platform without going bankrupt: Part IV–Caching and distribution - 3 days from now
  5. Building a social media platform without going bankrupt: Part V–Handling the timeline - 4 days from now

And 5 more posts are pending...

There are posts all the way to Feb 05, 2021

RECENT SERIES

  1. Webinar recording (12):
    15 Jan 2021 - Filtered Replication in RavenDB
  2. Production postmortem (30):
    07 Jan 2021 - The file system limitation
  3. Open Source & Money (2):
    19 Nov 2020 - Part II
  4. re (27):
    27 Oct 2020 - Investigating query performance issue in RavenDB
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats