Telerik blogs

Previously , I have posted how it is possible to mock a method without passing the dependency through a constructor / calling method. This is something true for third party controls and tools where we have little control over how its created.

You can find more on that in the following post:

http://weblogs.asp.net/mehfuzh/archive/2011/07/21/fake-a-member-without-worrying-about-passing-the-dependency.aspx

 

Now the feature that lets you mock  members without passing the dependency, we call it Future mocking. However it does not mean that Justmock ignores the instance completely but rather there is a workflow where it checks if there is no match for instance (of course it is a profiler intensive feature) and mocked within current context it tries to match any setup that is meant for.

One of the best example that I recently encountered through a community feedback that describes a UI case where based on some action against the form, raises an event which needs to be handled in a specific way in the unit test to assert the expected value.

Therefore, we have a Form class where the constructor looks something like:

 

  1.  
  2. public Form2()
  3. {
  4.     InitializeComponent();
  5.  
  6.     this.service = new EntryService();
  7.  
  8.     service.Saved += new EventHandler<EntrySavedEventArgs>(service_Saved);
  9. }            

 

We have a SaveToDatabase method that on the other hand invokes the Save method in EntryService and finally raise an event when successfully saved.

 

  1. public void SaveToDatabase(string value)
  2.     {
  3.         try
  4.         {
  5.             this.service.Save(value);
  6.         }
  7.         catch (DuplicateEntryException ex)
  8.         {
  9.             MessageBox.Show("Entry Duplicated " + ex.DuplicatedValue);
  10.         }
  11.         catch (ArgumentNullException)
  12.         {
  13.             this.label1.Text = "Valeur manquante";
  14.         }
  15.     }

 

Here  for now lets consider our event target will have just the following block:

 

  1. void service_Saved(object sender, EntrySavedEventArgs e)
  2. {
  3.     this.label1.Text = "Saved string : " + e.EntryValue;
  4. }

 

In the first snippet we can see that EntryService is created in  the constructor of Form2 class and therefore not injected via some external class/agent. The thing that the particular user wanted to do is to raise the target event with the expected EntryValue that is passed during SaveToDatabase call. So the specification for it that verifies such follows:

 

  1. [Subject(typeof(Form2))]
  2. public class when_save_to_database_is_invoked_on_form
  3. {
  4.     Establish context = () =>
  5.     {
  6.         IEntryService serviceMock = Mock.Create<EntryService>();
  7.         Mock.Arrange(() => serviceMock.Save(valueToSave)).Raises(() => serviceMock.Saved += null, new EntrySavedEventArgs(valueToSave));
  8.         sut = new Form2();         
  9.     };
  10.  
  11.     private Because of = () =>
  12.     {
  13.         sut.SaveToDatabase(valueToSave);
  14.     };
  15.  
  16.     private It should_assert_that_label_contains_expected_valueToSave = () =>
  17.         sut.label1.Text.ShouldEqual("Saved string : " + valueToSave);
  18.  
  19.  
  20.     static Form2 sut;
  21.     const string valueToSave = "Raise Event";
  22. }

Here we can see that although no instance is supplied to the target UI class JM picks up the intended setup from the context. Needless to mention that in code there are smells like labe1 is private and is accessed by specifying InternalsVIsibleTo  for specification assembly but rather it should be implemented using MVVM and {Binding Label1 } way. But that is out of the scope of this post and leave that to the reader. I would further thank Vincent Grondin for the project and you can try this out with the latest release as of today.

You can further download the sample project here:

 

Finally, hope this has given you an idea on getting started with future mocking.

Thanks


Comments

Comments are disabled in preview mode.