1

I have following questions related to the code unit tests for the classes which are pretty much integrated with the database logic. E.g. My class method calls another class that executes a database query or stored procedure.

If I don't want to to involve real database during unit testing what are the options?

Many people use the interface driven approach in which I will have to declare an interface. Then during unit testing, I will have to provide an implementation of the interface which does not work with the real database.

I know that in real world I will not have various implementations of the same interface. So the concrete class is OK for me. But is it advisable to declare an interface just for the sake of unit testing?

If we declare an interface and write unit tests using it, I may want to decide an implementation during test execution, then we may have to start thinking of the IoC containers to inject concrete class at runtime. Now this makes application unnecessarily complex.

How to deal with this?

Learner
  • 4,661
  • 9
  • 56
  • 102
  • 1
    It's a matter of taste I guess. In my experience the extra time it takes to extract an interface is minimal compared to the reduced complexity of the unit tests. See also [this](http://programmers.stackexchange.com/questions/159813/do-i-need-to-use-an-interface-when-only-one-class-will-ever-implement-it) discussion on programmer exchange – Hintham Jul 03 '15 at 10:06
  • 3
    just because you introduce an interface it doesn't mean that you need an IoC container all of a sudden. An IoC container is a tool which can help to simplify complex object graph construction, but this can ALWAYS be done without the container. And in your unit tests you should be creating small simple object graphs (as you are only testing small units) you shouldn't need an IoC container to create the object graphs. Just 'new' up the objects under test with the mocked dependencies – Sam Holder Jul 03 '15 at 10:18

2 Answers2

0

In general you can do that, but it depend on what mocking library you use. For Moq you can just use Setup method for mocking result of the methods. Usually as you said it's prefferable to use interfaces, but you can do that without interfaces:

c# - How do I mock a class without an interface?

Anyway from architecture and loosing coupling perspective it's reasonable to use Interface Driven Development approach.

Community
  • 1
  • 1
Piotr Czarnecki
  • 1,688
  • 3
  • 14
  • 22
  • I agree. But when I know that there wont be different implementation of the interface, is it right to bring in interface and IoC container etc just for unit testing? Why to make actual application complex for it? – Learner Jul 03 '15 at 10:11
  • For me it's perfectly ok. Of course it depends on your approach, so if in your opinion it's too much effort to write interface and handle some IoC container it's ok to not do it, but if you think that it will simplify writing unit test for you I believe it's worth to do it. – Piotr Czarnecki Jul 03 '15 at 10:31
0

If you don't want to hit your database, you've basically got two options:

  • Use an alternate database, possibly an in memory one.
  • Create some separation between yourself and the database, usually by mocking out the interactions.

With the majority of mocking frameworks (all the free ones) and with hand rolled mocks, you need to be able to supply your mocked instance to the class that you want to test. You have to do this, whether or not you're mocking a concrete class, or an interface. This is done through dependency injection. The general consensus seems to be that constructor injection is preferred, although property injection is also an option if that's what works for you.

Whilst IOC containers can help with dependency injection, they aren't the only way to do it. You can have your classes client create the object before instantiating your class:

public void SomeMethod(string someParam) {
    var db = new SomeDbClass();     // Create db dependency
    var job = new SomeDbClient(db); // Create class that uses db
    job.SomeMethod(someParam);      // call some method...
}

You can also just use a defaulted constructor like this:

public SomeDbClient(ISomeDependency dependency = null) {
    if(dependency == null) {
       dependency = new SomeDependency();
    }
    _dependency = dependency;
}

You're existing code doesn't need to change to support the defaulted constructor, but it allows you to injected a mocked version of the dependency from your tests. This can be a useful transition stage if you're moving towards dependency injection and you're not sure about moving all the way to an IOC container.

The injected dependency can be an interface, or a concrete class, however if you want to be able to mock aspects of the injected class, it'll need to declare the relevant functions as virtual so that your mocks can override the behaviour.

Community
  • 1
  • 1
forsvarir
  • 10,749
  • 6
  • 46
  • 77