简体   繁体   中英

How to Unit Test without testing private methods calling database

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?

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.

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.

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM