Search code examples
c#unit-testingdependency-injectionmockingmoq

How do I trigger a specific condition inside a method if I cannot inject a mocked object into it?


What must I do to create a unit test that causes searchResult to be null so that MyMethod returns false?

public class MyConnectionHandler
    public bool MyMethod()
    {
        var myConnection = new LdapConnection(...);
        var searchResult = myConnection.Search(...);

        if (searchResult == null) return false;
        return true;
    }
}

I'm encountering these problems:

  1. I'm unable to mock myConnection because it's not injected as a dependency, and I prefer not to make it injectable because no other class than MyConnectionHandler will be using it.
  2. The Search function connects to an external server that I could configure to return null, but I prefer that the test depends on its own configuration rather than that of an external server.

I probably need to refactor the class, but it's unclear to me how to do that correctly and I much appreciate your help.


Solution

  • If this line of code

    var myConnection = new LdapConnection(...);
    

    somehow reads some configuration information that you can intercept, and if you can stand up an in-memory LDAP server, like you can stand up an automatically configured database (SQL) server, you may be able to write an integration test that verifies the code path that you're interested in.

    If that's not possible...

    I probably need to refactor the class

    Yes, you do, and the easiest way to do that is to inject the dependency, even though you wrote that you don't want to do that.

    and I prefer not to make it injectable because no other class than MyConnectionHandler will be using it.

    That may not be the best criterion for deciding what gets injected and what doesn't. Rather, you should model those dependencies that are real dependencies as interfaces or base classes, and little more. This is because these are your inescapable sources of non-deterministic behaviour, and since you want tests to be deterministic, you want to be able to control those dependencies from your test.

    Thus, MyConnectionHandler should look like this:

    public class MyConnectionHandler
        private readonly ILdapConnection myConnection;
    
        public MyConnectionHandler(ILdapConnection myConnection)
        {
            this.myConnection = myConnection;
        }
    
        public bool MyMethod()
        {
            var searchResult = myConnection.Search(...);
    
            if (searchResult == null) return false;
            return true;
        }
    }
    

    Now you can create a Test Double and inject it into an instance of MyConnectionHandler.