0

I'm like doing TDD so I started everything mocking objects, creating interface, stubbing, great.

The design seems to work, now I'll implement the stuff, a lot of the code used in the stubs are going to be reused in my real implementation yay!

Now should I duplicate the tests to use the real object implementation (but keeping the mocks object of the sensitive stuff like Database and "services" that are out of my context (http calls, etc...)) Or just change the mocks and stubs of the actual tests to use the real objects.......

So the question is that, keep two tests or replace the stubs, mocks?

And after that, I should keep designing with the mocks, stubs or just go with real objects?

(Just making myself clear I'll keep the mock object of the sensitive stuff like database and services that are out of my context, in both situations.)

EDIT

[Fact]
public void Change_status()
{
    var dbContext = MockRepository.GenerateStub<IDbContext>();
    var repository = MockRepository.GenerateMock<IRepository<Foo>>();

    var predicate = MockRepository.GenerateStub<Func<Foo, bool>>();
    repository.Expect(x => x.Get(predicate)).Return(_foo).Repeat.Once();
    dbContext.Expect(x => x.Commit());

    var ctl = MockRepository.GenerateStub<IFooCtl>();
    ctl.Stub(x => x.RejectRequest(_fooView)).WhenCalled(delegate
    {
        var foo = repository.Get(predicate);
        foo.Status = Status.Rejected;
        _fooView.Status = Status.Rejected.ToString();

    }).Return(true);

    ctl.RejectRequest(_fooView);

    repository.VerifyAllExpectations();
    dbContext.VerifyAllExpectations();
    Assert.True(_fooView.Status == "Rejected");
    Assert.True(result.Count() == 1);
}

This is a test, where I mock the repository, context and stub the facade. So what I'm trying to say is if I should change the stub of the facade to use the "real" code so this should be tested as

[Fact]
public void Change_status()
{
    var dbContext = MockRepository.GenerateStub<IDbContext>();
    var repository = MockRepository.GenerateMock<IRepository<Foo>>();

    var predicate = MockRepository.GenerateStub<Func<Foo, bool>>();
    repository.Expect(x => x.Get(predicate)).Return(_foo).Repeat.Once();
    dbContext.Expect(x => x.Commit());

    var ctl = new FooCtl(loanRepository, happyLoanDbContext);
    var result = ctl.RejectRequest(_loanView);

    repository.VerifyAllExpectations();
    dbContext.VerifyAllExpectations();
    Assert.True(_result);
}

Or if I should leave everything mocking and stubbing that tests the designs and create new ones that tests the implementation.

EDIT

Thanks for all your answer, I think I understand it better, I must know which is my SUT and test that, no mock or stub the SUT just the components that will help the SUT to pass the test

4 Answers 4

10

Or if I should leave everything mocking and stubbing that tests the designs and create new ones that tests the implementation.

A unit test never tests abstractions, or designs as you put it. It always tests one concrete implementation, that of the class under test.

In other words, if you have a test fixture for class A where you mock or stub out A's dependencies B and C, then you're not testing B and C's behavior or design. You're only testing A's behavior and that it is able to talk to B and C properly. In order to test concrete implementations of B and C, you have to create dedicated tests fixtures for both of them.

From a purely isolated unit test perspective, you neither need to substitute mocks for real implementations afterwards, nor to create integration test counterparts besides your unit tests (integration tests = tests involving several concrete implementations at the same time). Your isolated unit tests should stay as they are, with all the mocks and stubs. They stand on their own provided that you test all concrete implementations and their interactions with their dependencies.

As Erik points out, you could create integration tests, but keep in mind that they come at a cost, both in terms of processing time and maintenance time, and they shouldn't replace unit tests as your primary test harness IMO.

7

It seems to me that you're asking whether you should turn your unit tests into integration tests. I would say the answer is decidedly no. I think that you'd be well served to keep the unit tests you're writing (the ones that use mock objects) as the backbone of your test suite.

For the integration tests (where you assemble larger parts of your application with actual objects instead of mocks), I'd have fewer of these, since they are necessarily more time consuming to run and much more involved to maintain. These are often good as "smoke tests", but I wouldn't have these be the focus of your test suite.

4
  • But when should I test the "real" code, since everything is mocked and stubbed, that will only test the design not the implementation of it.
    – jjchiw
    Jun 26, 2012 at 0:24
  • As for the "when", I think most people run unit tests regularly (either continuously with a tool or as often as saving files) while they develop. Integration tests are probably run about as often as source code promotions/deliveries happen. Beyond that, I'm not really sure what you mean by "design versus implementation". Using mocks is designed to isolate your classes so that you can test them individually without juggling too many balls at once. Your unit tests are testing implementation. Jun 26, 2012 at 3:05
  • The "when" was not about how often the test should be run. What I'm trying to ask is that I can design a app with just mocks, stubs and test everything....I edited the question, hope make it more clearer what my "dilemma" is....thanks
    – jjchiw
    Jun 26, 2012 at 6:45
  • 1
    @jjchiw the point of testing in isolation is not to mock out everything, but just what is necessary to verify only your System Under Test (SUT). When you're testing A, you don't want a malfunction in B to interfere with your test's result, so you mock out B. It's that simple. See my answer and stackoverflow.com/questions/2204433/… Jun 26, 2012 at 12:35
4

The idea of TDD is that you concentrate about implementing only one thing at the time. So when implementing a class you discover that you need some external class you should not start implementing that, but simply make a stub or even better just an interface, that has just enough functionality to make the class that you are actually implementing work.

Mocks are used to be sure that you test only one thing. Only one class. So even if you have implemented real classes in place of the stubs/interface you made to temporary cover for some missing functionality, the mocks should always be there to test that class in isolation (part of you automatic test suite). When you move on to implement an actual class instead of the stub, you should also make a mock object to represent the class you started out implementing.

Hope that helps.

1
  • Ok, so instead of mocking and stubbed everything at first I should be implementing the stuff while doing the Tests and just mocking what I would expect to fail or succes...
    – jjchiw
    Jun 26, 2012 at 0:23
2

Your "real" classes might look like mocks now, but in the future they could change drastically. Do you really want future changes in your real classes to have an effect on other unit tests? I doubt it. Write mock classes for unit tests and real classes for real code, and if they happen to look the same, that's ok.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.