0

I am facing difficulties understanding how to well unit-test my application.

Let's say I have a public method publicMethod() calling several private methods holding the business logic. I learned that private methods shouldn't be unit-tested, so I need to unit-test publicMethod().

The problem is that my private methods at some point access the database. As I am not unit-testing the private methods, I cannot fake the database call. What I can do is fake the private method call, but then if I fake it I lose all interest of the test as the business logic isn't tested anymore.

What is the solution so I can unit-test the logic in this case?

realUser404
  • 2,111
  • 3
  • 20
  • 38
  • "I learned that private methods shouldn't be unit-tested" I don't think you strictly mean this. Your tests should be testing the business logic you have written. – JamesB Dec 03 '14 at 09:59
  • What exactly do you mean by 'faking'? Can you add a code example? Have you worked with a mocking framework yet? – reto Dec 03 '14 at 10:00
  • It's called mocking, and if the method doesn't have any functionality beyond its mocks it's delegating, and doesn't have to be unit-tested. – keyser Dec 03 '14 at 10:09
  • 1
    If you have problems with unit testing, there is usually a problem with your software design. It's hard to provide a solution without knowing your concrete design, but maybe you can extract the database access into another class which implements an interface. Then you can mock this interface in your unit test. – Thomas Lielacher Dec 03 '14 at 10:15
  • You do unit test private methods, but you do it through testing the public methods that call them. So yes indeed, faking the private methods is not going to be much help. What you need is a way to mock out the database calls from the private methods. So either inject a connection to a test database the contents of which are under your full control, or abstract out the database calls and mock those. – Marjan Venema Dec 06 '14 at 17:57
  • This question overlaps http://stackoverflow.com/questions/34571/how-to-test-a-class-that-has-private-methods-fields-or-inner-classes?rq=1 – Raedwald Feb 18 '15 at 19:49

3 Answers3

2

Well, it's difficult to point to a solution without more input, but I'll try to offer some ideas (hope they help). I would like to argue, like JamesB points out, that you want to unit test everything that has business logic inside it.

From your question maybe you're having some trouble separating reponsabilities in your program. It seems you have an entry point publicMethod(), and several private methods that manage the business logic. By accessing the database inside the same object, you are coupling the data layer to the business logic. By making those methods use a data provider instead, you can configure your object to read from another data source you can control to guide your test and without making it dependant of state.

VVP
  • 81
  • 2
1

Take a look at http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html which is perfect for you. Mocking is simulating another unit so that you can stick with pure unit testing.

I assume here that you have your business logic and data access logic in 2 different classes. If not, you should probably clean that up first. Never stick business logic and data access logic in one class.

Robin-Hoodie
  • 4,886
  • 4
  • 30
  • 63
1

This is why you shouldn't do data access logic directly in your business logic class, but rather have a separate class that handles the database access (like for example a repository). Take a look at the Repository & UnitOfWork Pattern

At the same time, you should use dependency injection and inject the interface of the repository. You can then create mocks of this interface and fake the database call like for example

var personRepositoryMock = new Mock<IPersonRepository>();
personRepositoryMock.Setup(x => x.GetPerson()).Returns(new Person());
xeraphim
  • 4,375
  • 9
  • 54
  • 102