From: http://martinfowler.com/articles/mocksArentStubs.html
I am going to try to explain you in one simple example the difference...
The classes involved:
FileProcessor: The actual business logic, that we are trying to test, the Subject Under Test
File: some file we are processing
FileValidator: Performs some logic on the file to see if it contains errors
FileMover: Moves the file to a specific location depending on the results returned by the FileValidator
public class FileProcessor{
private readonly IFileMover _FileMover;
private readonly IFileValidator _FileValidator;
//Constructor
public FileProcessor(IFileMover fileMover, IFileValidator fileValidator){
IFileMover _FileMover = fileMover;
IFileValidator _FileValidator = fileValidator;
}
public void Process(File file){
ValidationResults result = _FileValidator.Validate(file);
if(result.IsValid){
_FileMover.Succes(file)
}else{
_FileMover.Error(file)
}
}
}
public interface IFileMover{
void Success(File file);
void Error(File file);
}
public class ValidationResults{
public virtual bool IsValid{
get;
}
}
public interface IFileValidor{
ValidationResults Validate(File file);
}
We need to create a dummy called DummyValidationResults
public class DummyValidationResults: ValidationResults{
public virtual bool IsValid{
get{ return false;}
}
}
Now we create a Mock MockFileMover
public class MockFileMover: IFileMover{
public void Success(File file){
this.SucessCalled++;
}
public void Error(File file){
this.ErrorCalled++;
}
public int SuccesCalled{get; private set;}
public int ErrorCalled{get; private set;}
}
We create a Stub named StubFileValidator
public class StubFileValidator: IFileValidator{
public ValidationResults Validate(File file){
return new DummyValidationResult();
}
}
now when we would like the test the Fileprocessor we can write:
File aFile = new FakeFile();
MockFileMover fileMover = new MockFileMover()
FileProcessor processor = new FileProcessor(new MockFileMover(), new StubFileValidator());
processor.process(aFile);
Assert.AreEqual(1,fileMover.ErrorWasCalled);
Assert.AreEqual(0,fileMover.SuccessWasCalled);
So what is the difference?
The stub returns a predetermined answer what needs to happen and the path through the code dictates it will always be called. As you can see the methods of the mock are enclosed in decision logic in this case an if statement (this can as wel be a try catch switch or whatever), then we verify if the correct method on the mock has been called... so the mock is responsible for failing or succeeding the test...