4

I am relatively new to unit testing and have a query about what/how I should be testing a certain method. For the following (psudo-c#) method I have created (not a real-life example) what would you test for?

Initially, my thoughts would be to test the output with variations on the dictionary of form fields, e.g. valid, invalid, missing values. However I also wonder how you would test to make sure the object values have been changed to the correct value and that the correct email message was attempted to be sent (obviously both services could/would be mocked).

I hope what I am asking makes sense, I appreciate this is a subjective question and the answers may be 'it depends' ;)

public bool ProcessInput(Dictionary<string, string> formFields, ObjService objService, EmailService emailService)
    {
        try
        {
                   // Get my object id
                   int objId;
                   if(!int.TryParse(formField["objId"], out objId)
                   {
                      return false;
                   }

                   // Update my object - would you validate the save against a DB or a mocked inmemory db?
                   var myObj = objService.Find(objId);
                   myObj.Name = formField["objName"];
                   objService.Save(myObj);

                   // Send an email - how would you test to make sure content, recipient, etc was correct? 
                   emailService.SendEmail(formField("email"), "Hello World");

                   return true;    
        }
        catch(Exception ex)
        {
        return false;
        }
    }
1
  • a slightly unrelated point, id probably pull the email stuff out of this function unless this is pretty much at the top level already. at the moment it feels like it breaks the SRP to me
    – jk.
    Aug 12, 2014 at 8:34

2 Answers 2

8

You are on the right track. You should be testing (at least) the following scenarios:

  1. invalid (non-integer) object ID: the method should return false and no changes should be made (i.e. no services called)
  2. unknown object ID: the method should probably behave similarly to case 1 (but currently it does not seem to handle that case)
  3. valid object ID, valid name in the form field: object should be saved to the object service, email should be sent
  4. valid object ID but missing name in the form field: similar to case 3???

Both ObjService and EmailService should be mocked in your tests, then you can verify that they are (not) called with the expected parameters.

4

Well I am not really an expert in the subject but I have done some of "unit testing" stuff.

Ideally, for unit testing, your method parameters must comprise of abstract types, something like

 public bool ProcessInput(IDictionary<string, string> formFields, IObjService objService, IEmailService emailService)

And so what your really want to test is ProcessInput and mocking away the email service and ObjService by creating a mock object of IEmailService and IObjservice using some library like Moq.

To answer what you must test, you may consider some of the test cases below

  • Passing a null object in formFields and see how your method treat null objects
  • Passing non-parsable kind of keys in dictionary
  • Passing a objID in dictionary which cannot be found by objService.Find(objId)
  • Some functional flows checking happy case...

That is what comes to my mind. Hope this helps. Please feel free to discuss further if there is something I am missing.

1
  • Sorry, yes you are correct the parameters should be interfaces.
    – user460667
    Mar 31, 2012 at 12:44

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.