State-based Testing : State-based testing is also known as state verification. The purpose of it is to exercise method(s) of an class under test whether the method(s) worked correctly by asserting the expected state of the class. For this, fake objects which are called stubs are used.
Stub : Stub is actually a fake object which is used to imitate a real object in order to test some state verifications.
Behavioral Testing : Some people use interaction based testing or action-driven testing instead behavioral testing. For performing behavioral testing, we use mock object which is fake object like stub.
Mock : Mock is actually fake object which is used to fake the real domain object for behavioral testing. In contrast to stub object, mock object can fail.
I'll write an simple example to perceive the implications of differences between stub and mock objects. Following code sample shows the real domain code. Login() method in LoginManager class is used to check whether email and password matches. If matched, write log message and set IsSaved property to true.
Creating Real Domain Classes and Interfaces
1: public interface IUser
2: {3: int Id { get; set; }
4: string Name { get; set; }
5: string Email { get; set; }
6: string Password { get; set; }
7: } 8: 9: public class User : IUser
10: {11: public int Id { get; set; }
12: public string Name { get; set; }
13: public string Email { get; set; }
14: public string Password { get; set; }
15: } 16: 17: public interface IUserRepository
18: {19: IUser GetUser(string email, string password);
20: } 21: 22: public interface ILogger
23: {24: void Save(string message);
25: bool IsSaved { get; set; }
26: } 27: 28: public class LoginManager
29: {30: private IUserRepository repository;
31: private ILogger logger;
32: public LoginManager(IUserRepository repository, ILogger logger)
33: {34: this.repository = repository;
35: this.logger = logger;
36: } 37: 38: public void Login(string email, string password)
39: {40: IUser user = this.repository.GetUser(email, password);
41: this.logger.Save(user.Name + " has been logged in");
42: this.logger.IsSaved = true;
43: } 44: }Writing Unit Testing with Stub Object
First of all, we should decide what we test. We'll make state-based testing by checking the IsSaved property of the Logger class. I'll use Rhino Mocks which you can download from http://www.ayende.com/projects/rhino-mocks.aspx .
I'll follow the following steps to write test code:
- Create instance of stub objects
- Set expectations
- Create a real domain object with stub objects
- Assert it
1: [Test]2: public void Login_EmailandPasswordIsCorrect_LogIsSaved()
3: {4: // create stub objects
5: var repository = MockRepository.GenerateStub<IUserRepository>(); 6: var logger = MockRepository.GenerateStub<ILogger>(); 7: 8: // set expectations
9: repository.Stub(x => x.GetUser(Arg<string>.Is.Anything,
10: Arg<string>.Is.Anything)).Return(new User());
11: 12: // create real domain object
13: LoginManager manager = new LoginManager(repository, logger);
14: manager .Login("test","password");
15: 16: // assert it
17: Assert.AreEqual(true, logger.IsSaved);
18: }On line 9, I used Stub method to set expectation with constraints. GetUser() method can only receive two string arguments and returns User object.
On line 13, I created an instance of a class which is under test and passed two stub objects into its constructor. Then i invoked Login() method with "dummy" arguments. If Login() method worked correctly, IsSaved property of Logger class must be set "true".
Finally, line 17th, i asserted that value of IsSaved property must be true.
It's nice to say that, I can test the method before implementing production code. Even if i haven't build Logger and UserRepository classes. After testing all cases, if tests pass, there is nothing to stop me to write production code.
Writing Unit Testing with Mock Object
I want to test behavioral verification. Therefore I'll use mock object. My purpose is to be sure that Save() method in Logger class is invoked with correct arguments.
1: [Test]2: public void Login_EmailandPasswordIsCorrect_LogSaveMethodRunsCorrectly()
3: {4: // create stub and mock objects
5: var repository = MockRepository.GenerateStub<IUserRepository>(); 6: var user = MockRepository.GenerateMock<IUser>(); 7: var logger = MockRepository.GenerateMock<ILogger>(); 8: 9: // set expectations
10: user.Expect(x => x.Id).Return(1);11: user.Expect(x => x.Name).Return("serkan");
12: user.Expect(x => x.Email).Return("test@technolatte.net");
13: user.Expect(x => x.Password).Return("123456");
14: 15: repository.Stub(x => x.GetUser(Arg<string>.Is.Anything,
16: Arg<string>.Is.Anything)).Return(user);
17: logger.Expect(x => x.Save("serkan has been logged in"));
18: 19: // create real domain object
20: LoginManager manager = new LoginManager(repository, logger);
21: manager.Login(string.Empty, string.Empty);
22: 23: // verify mock object
24: logger.VerifyAllExpectations(); 25: }Line 6th and 7th, I created two mock objects and line 5th i created one stub object.
I set mock objects with expected values.
On line 17, I used Expect() method to assume that Save() method of Logger class would be invoked with string argument which is equal to "serkan has been logged in".
Line 24th, i verified all expectations.
It's useless and less efficiency to write unit testing without knowing the differences between mock and stub objects. .
- Stub can't fail test but mocks can.
- Stub is used for state-based testing, mock is used for behavioral testing.
- Mock objects keep the history of communication which will be verified later.
- The mock object is covered by a specification of expectation for the calls it’s expected to receive. Stub contains of preserved responses to requests that are sent during the test process.
Every fake object you create is stub by default unless if you want to test it. Otherwise it's called mock. If you verify calls against it, it's a mock, otherwise it's a stub.
Finally, I suggest the article written by Martin Fowler on his own web site about distinction of mock and stub to understand better what the differences are.



