I have three functions:

  • ValidateUsername(), which determines if a string is a valid username according to some rules
  • SetUsername() which sets a string as a user's Username if it passes validation
  • AddNewUser(), which creates a new user and, among others, sets a string as his or hers Username using SetUsername()

All three should fail if the supplied username string is incorrect, yet ValidateUsername() is where the rules reside. How would I unit test this? Testing validation only in ValidateUsername() leaves the possibility that someone will mistakenly omit validation and set the username directly in AddNewUser(). On the other hand, repeating all different validation test cases for all functions seems counterproductive. What's the best practice?


3 Answers 3


Unit testing is called that way because you are intending to test units of work, in your case each method is a unit of work and not the whole integration between them.

Let's assume your business requirement for ValidateUsername() method is to validate the user name according to certain requirements. Your unit test in this case should verify that validation was correct and rules are implemented correctly.

Now seems like for you other methods, one of the business requirements is to call validation method - do just that. Ensure that the ValidateUsername was called indeed. You don't care whether it was executed correctly or not - that part is to be tested by your previous test for ValidateUsername unit.

  • 1
    Thanks, I ended up mocking the validating class containing the validation method to check if it was called. This seemed practical as I want all validation logic to live inside it.
    – io-quois
    Jun 24, 2015 at 12:17
  • 1
    Well done, Mocking is what needed to do :)
    – Alexus
    Jun 24, 2015 at 17:24
  • Just be careful though as mocking will only test that the SetUsername function called the ValidateUsername function but not that it (SetUsername) then did anything with that result... it could have just ignored it. If the SetUsername function is touching a datastore you could test the correct value is stored. For the AddNewUser, you can test the function/API returns an error or returns a new user with the validated/corrected user name.
    – AJP
    Dec 7, 2023 at 14:02

You can verify that the validation function was called by testing the other two functions with one invalid name and one valid name. Or you can separate the logic into UsernameValidator and UserService, and inject the validator into the user service. Then you test the user service by mocking the validator.


If I'm interpreting your question correctly, AddNewUser() calls SetUsername(), and SetUsername() calls ValidateUsername(). Two options come to mind:

1) Keep the existing structure, and write unit tests for the "one thing" that each function is responsible for, while assuming the "happy path" for its dependencies. So the ValidateUsername() tests would check valid and invalid usernames, the SetUsername() test would pass in a valid username and make sure that username ends up in the right place, and the AddNewUser() test would pass in valid user-construction data and make sure a user got added using that data.

2) Change the structure to something "flatter" so that the functions no longer depend on each other. So you might have a AttemptToAddUser() function that calls ValidateUsername(), then SetUsername(), then AddNewUser() all at the same level of the call stack.

The optimal answer depends heavily on your exact code, but I would expect it to be either #1 or something between #1 and #2. It might make perfect sense to pull ValidateUsername() up to the same level as AddNewUser(), but I have a hard time imagining a SetUsername() function being of any use outside the AddNewUser() function (assuming it's not a method on a User object or something).

And of course, regardless of how the unit tests work, you probably still want a small number of integration tests that check all of these functions together.

  • Option (1) would not test all relevant code-paths of SetUsername() and AddNewUser(). Option (2) calls for bad coding habits (copy-and-pasting idioms). I don't like either. Feb 8, 2021 at 23:16

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