I have already had some difficulties on unit tests and I am trying to learn it while using a small project I currently am working on and I ran into this problem these two problems that I hope you can help me with
1- My project is an MVC project. At which level should my unit tests start? They should focus only on the business layer? Should they also test actions on my controllers?
2- I have a method that verifies an username format and then access the DB to check if it is available for use. The return is a boolean whether this username is available or not.
Would one create a unit test for such a method?
I would be interested on testing the format verification, but how would I check them without querying the DB? Also, if the formats are correct, but the username is already in use, I will get a false value, but the validation worked. I could decouple this method, but the DB verification should only happen if the format is correct, so they should somehow be tied.
How would someone with unit tests knowledge solve this issue. Or how would someone refactor this method to be able to test it?
I could create a stub for the DB access, but how would I attach it to my project on the user testing but detach it when running locally?
Thanks!
In your specific case, one easy thing you could do is decompose your verification method into 3 different methods: one to check formatting, one to check DB availability, and one to tie them both together. This would allow you to test each of the sub-functions in isolation.
In more complex scenarios, other techniques may be useful. In essence, this is where dependency injection and inversion of control come in handy (unfortunately, those phrases mean different things to different people, but getting the basic ideas is usually a good start).
Your goal should be to decouple the concept of "Check if this username is available" from the implementation of checking the DB for it.
So, instead of this:
public class Validation
{
public bool CheckUsername(string username)
{
bool isFormatValid = IsFormatValid(username);
return isFormatValid && DB.CheckUsernameAvailability(username);
}
}
You could do something like this:
public class Validation
{
public bool CheckUsername(string username,
IUsernameAvailabilityChecker checker)
{
bool isFormatValid = IsFormatValid(username);
return isFormatValid && checker.CheckUsernameAvailability(username);
}
}
And then, from your unit test code, you can create a custom IUsernameAvailabilityChecker which does whatever you want for testing purposes. On the other hand, the actual production code can use a different implementation of IUsernameAvailabilityChecker to actually query the database.
Keep in mind that there are many, many techniques to solve this kind of testing problem, and the examples I gave are simple and contrived.
Testing against outside services can be done using mocking. If you've done a good job using interfaces it's very easy to mock various parts of your application. These mocks can be injected into your unit and used like it would normally handle it.
You should start unit testing as soon as possible. If your application is not complete or code needed for testing is absent you can still test against some interface you can mock.
On a sidenote: Unit testing is about testing behavior and is not an effective way to find bugs. You will find bugs with testing but it should not be your goal.
For instance:
interface UserService {
public void setUserRepository(UserRepository userRepository);
public boolean isUsernameAvailable(String username);
}
class MyUserService implements UserService {
private UserRepository userRepository;
public vois setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public boolean isUsernameAvailable(String username) {
return userRepository.checkUsernameAvailability(username);
}
}
interface UserRepository {
public boolean checkUsernameAvailability(String username);
}
// The mock used for testing
class MockUserRepository {
public boolean checkUsernameAvailability(String username) {
if ("john".equals(username)) {
return false;
}
return true;
}
}
class MyUnitTest {
public void testIfUserNotAvailable() {
UserService service = new UserService();
service.setUserRepository(new MockUserRepository);
assertFalse(service.isUsernameAvailable('john')); // yep, it's in use
}
public void testIfUserAvailable() {
UserService service = new UserService();
service.setUserRepository(new MockUserRepository);
assertTrue(service.isUsernameAvailable('mary')); // yep, is available
}
}
Related
As a person has no experience before in unit testing and mocking, I followed beginner tutorials about JUnit with Mockito and I do some practice.
Now, I need to unit test some class methods which do basic database operations on a MySQL database. I don't want to make real changes on the database.
In my code:
#InjectMocks private DBConnection dbConnection;
#Mock private DBConnection mockDBConnection;
#Test
public void testDropTable() {
Mockito.when(mockDBConnection.dropTable()).thenReturn(0);
// dropTable() returns 0 if table dropped
int result = dbConnection.dropTable();
Assert.assertEquals(result, 0);
}
To verify(with assertEquals() ) result of the test, I am calling real dropTable() method, and it really drops table( Actually it is obvious, because I'm calling on real DBConnection instance)
Is there anyway to verify the methods like that, without accessing the real database? Or did I misunderstand the concept of Unit Testing and Mocking?
Imagine the following... You have two cars, one is a real car, another is a fake (mock) car. Now you get into the real car and drive off. Why do you expect not to move? You didn't do anything with the fake car, so even if you told it "Do not move if I start driving", this doesn't change the fact that the real car WILL move when you drive off.
Same thing here, you created a fake DBConnection and a real one. The real one will do whatever the real one does. The fake one can be configured to do different stuff, like you did with Mockito.when(...). But that doesn't change the behavior of the real one.
Your test is effectively meaningless, because your only choice here is to get rid of the mock, because it doesn't serve any meaningful purpose. You do not test a mock. What for? That's like creating a fake car and testing that - it doesn't tell you anything about the real car. You do not need to test the fake car to find out that it will do X if you told it to do X in that test.
There are two ways you can test your DBConnection class:
a) You can connect it to a database and check that it does what it should. This would, of course, be an integration test and not a unit test anymore. In some cases you can use a in-memory database like HSQLDB to speed up this test. But at least in the end you can be reasonably sure that your code does what it is supposed to be doing.
b) IF and only IF DBConnection has some objects internally that do the actual talking to the database, you can, perhaps, mock those and then test DBConnection. Of course, this only moves your problem to another layer, because then you aren't sure that those objects work - you will only know that DBConnection works IF those objects work. While this is good to know, it does not answer the question if your db code will work in the end.
In the end, you can only test db connections completely by connecting to a db. Everything else is not a complete test.
Why not consider using an in-memory database for your unit tests. Maybe using a DAO pattern to easily switch between real and in-memory.
Keep the actual database interaction layer thin as possible to ensure you abstract your logic away in separate classes, this makes testing much easier, as in this case you can mock the DB object and focus on testing your logic.
Also decide what you are testing, most likely you want to test your logic, not the logic of the 3rd party database connector, so focus your tests on that.
Consider a suite of Integration or System tests to test the applications features against a real database, should you require this level of testing, but for unit tests, in-memory should be fine.
The overall confidence of your app can be achieved using be a combination of unit and integration tests.
For the #Florian Schaetz's comment, do I need to do something like that:
AuthenticatorApplicationInterface.java
public interface AuthenticatorInterface {
public boolean authenticateUser(String username, String password) throws EmptyCredentialsException;
}
AuthenticatorApplication.java
public class AuthenticatorApplication {
private AuthenticatorInterface authenticator;
public AuthenticatorApplication(AuthenticatorInterface authenticator) {
this.authenticator = authenticator;
}
public boolean authenticate(String username, String password) throws NotAuthenticatedException {
boolean authenticated;
authenticated = this.authenticator.authenticateUser(username, password);
return authenticated;
}
}
AuthenticatorApplicationTest.java
public class AuthenticatorApplicationTest {
#Test
public void testAuthenticate() throws EmptyCredentialsException {
AuthenticatorInterface authenticatorMock;
AuthenticatorApplication authenticator;
String username = "username";
String password = "noncorrectpassword";
authenticatorMock = Mockito.mock(AuthenticatorInterface.class);
authenticator = new AuthenticatorApplication(authenticatorMock);
when(authenticatorMock.authenticateUser(username, password)).thenReturn(false);
boolean actual = authenticator.authenticate(username, password);
assertFalse(actual);
}
}
I am trying to write a Unit Tests to a legacy code using Mockito.
But I am not able to understand how do I mock it. Can some please help.
The real problem I am facing is actually I am not able to decide how to make a decision on what exactly is to be mocked? Below is the code. I have looked at numerous videos on YouTube and read many Mockito Tutorials but all of them seem to be guiding mostly about how to use the Mockito Framework.
The basic idea of what to Mock is still unclear. Please guide if you have a better source. I do understand that the code showed below does not really showcase the best coding practice.
public class DataFacade {
public boolean checkUserPresent(String userId){
return getSomeDao.checkUserPresent(userId);
}
private SomeDao getSomeDao() {
DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
SomeDao someDao = new SomeDao(dataSource);
}
}
Well, a Unittest, as the name implies, tests a unit. You should mock anything that isn't part of that unit, especially external dependencies. For example, a DAO is normally a good example for something that will be mocked in tests where the class under tests uses it, because otherwise you would really have actual data access in your test, making it slower and more prone to failure because of external reasons (for example, if your dao connects to a Datasource, that Datasource's target (for example, the database) may be down, failing your test even if the unit you wanted to test is actually perfectly fine). Mocking the DAO allows you to test things independently.
Of course, your code is bad. Why? You are creating everything in your method by calling some static factory method. I suggest instead using dependency injection to inject the DAO into your facade, for example...
public DataFacade(SomeDao someDao) {
this.someDao = someDao;
}
This way, when instantiating your DataFacade, you can give it a dao, which means, in your test you can give it a mock, for example...
#Test
public void testSomething() {
SomeDao someDaoMock = Mockito.mock(SomeDao.class);
DataFacade toTest = new DataFacade(someDaoMock);
...now you can prepare your mock to do something and then call the DataFace method
}
Dependency injection frameworks like Spring, Google Guice, etc. can make this even easier to manage, but the first step is to stop your classes from creating their own dependencies, but let the dependencies be given to them from the outside, which makes the whole thing a lot better.
You should "mock" the inner objects that you use in your methods.
For example if you write unit tests for DataFacade->checkUserPresent, you should mock the getSomeDao field.
You have a lot of ways to do it, but basically you can make getSomeDao to be public field, or get it from the constructor. In your test class, override this field with mocked object.
After you invoke DataFacade->checkUserPresent method, assert that checkUserPresent() is called.
For exmaple if you have this class:
public class StudentsStore
{
private DbReader _db;
public StudentsStore(DbReader db)
{
_db = db;
}
public bool HasStudents()
{
var studentsCount = _db.GetStudentsCount();
if (studentsCount > 0)
return true;
else
return false;
}
}
And in your test method:
var mockedDb = mock(DbReader.class);
when(mockedDb.GetStudentsCount()).thenReturn(1);
var store = new StudentsSture(mockedDb);
assertEquals(true,store.HasStudents());
I am trying to figure out the right way to break up my unit tests.
Given the following two classes, one is a CategoryService and the other is a CategoryValidator using FluentValidation, how would you write these tests?
I have tried writing a test for the service and one for the validator, but how do I test that the validation works in the service? Or is that out of scope of the test for the service and should be covered in the validator test?
In the AddCategory method, I am testing that the category name does not already exist in the validator. How do I test that in a unit test? Or is that an integration test?
Category Service
public class CategoryService : ValidatingServiceBase, ICategoryService
{
private readonly IUnitOfWork unitOfWork;
private readonly IRepository<Category> categoryRepository;
private readonly IRepository<SubCategory> subCategoryRepository;
private readonly IValidationService validationService;
public CategoryService(
IUnitOfWork unitOfWork,
IRepository<Category> categoryRepository,
IRepository<SubCategory> subCategoryRepository,
IValidationService validationService)
: base(validationService)
{
this.unitOfWork = unitOfWork;
this.categoryRepository = categoryRepository;
this.subCategoryRepository = subCategoryRepository;
this.validationService = validationService;
}
public bool AddCategory(Category category)
{
var validationResult = validationService.Validate(category);
if (!validationResult.IsValid)
return false;
categoryRepository.Add(category);
return true;
}
}
Category Validator
public class CategoryValidator : AbstractValidator<Category>
{
public CategoryValidator(ICategoryService service)
{
RuleFor(x => x.Name)
.NotEmpty()
.Must((category, name) =>
{
return service.GetCategories().SingleOrDefault(x => x.Name == name) == null;
});
}
}
Some people might find this heresy but I prefer to have things under test even if the test is bordering on that of a integration rather than unit. You just need to make sure your checks are comprehensive.
Don't worry about how the tests interact between classes, if you are starting out in unit testing (as I suspect you are) then it is better to write tests and the final D of TDD will come naturally.
I think you should test validator and service separately. Say for service test you can mock validator to return specific results without polluting your test logic with too many details (pseudo-code)
test Should_Add_Category_Only_If_It_Is_Valid() {
//given
Category category = GivenACategory();
GivenValidatorAcceptsCategory(category);
//when
Bool result = service.AddCategory(category);
//then
AssertTrue(result);
VerifyServiceHasCategory(category);
}
test Should_Reject_Invalid_Category() {
//given
Category category = GivenACategory();
GivenValidatorRejectsCategory(category);
//when
Bool result = service.AddCategory(category);
//then
AssertFalse(result);
VerifyServiceDoesNotHaveCategory(category);
}
What you're addressing is beyond the definition of unit tests. Unit tests test units ;) So write unit test for the service with stubbed validator, and for the validator with stubbed service. Then write some integration tests and these will validate whether your components interact properly.
However, it's always a matter of how you define a component (a unit) in your system. If you expose the functionality of the service and the validator together as a package, then write unit tests for them together, treating them as one unit, and don't bother thinking how they work inside - expect just correct results of particular "API" (in the meaning - exposed interface) calls.
You can combine these two approaches, and test service and the validator as one unit, but being aware of it's internals using the White-box testing approach. However, this is discouraged for large components, and I think it's obvious why.
Finally - do all these names matter? They are just names, can't I have just tests? IMHO, it is important to denote the boundary between unit tests - which should test absolutely everything (meaning "every unit" - see above). This gives you flexibility and ability to refactor and restructure the code any time you want, without the risk of changing the external behavior of the units. The second group are additional tests (like integration, smoke, white-box, regression tests etc.) - because they test larger parts of the system, they are substantially less numerous. They are important, because unit tests can't verify all interactions between the components, but they test only some of possible scenarios.
How can you mock LLBLGen? I see that there is an ILinqMetaData interface but it doesn't provide any useful methods to mock out. I'm assuming you would want to program to the ILinqMetaData interface as well as the generated entity interfaces to keep objects loosely coupled to the data. Does anyone have any examples of simple tests/mocks?
I think it's not limited to LLBLGen, maybe this can help:
What's the best strategy for unit-testing database-driven applications?
Personally, I don't normally test my database access or repositories, just the logic that operates on the entities, or integration tests that operate on the entire stack (including the DB).
UPDATE: does this help? it allows you test your logic by mocking the IOrderRepository without having to do any fetch/persistence logic:
public class MyBusinessLogic
{
IOrderRepository orders;
public MyBusinessLogic(IOrderRepository orders)
{
this.orders = orders;
}
public DoSomethingTestable(OrderEntity order)
{
order.Total = 100;
orders.Save(order);
}
}
Given problem:
I like unit tests.
I develop connectivity software to external systems that pretty much and often use a C++ library
The return of this systems is nonndeterministic. Data is received while running, but making sure it is all correctly interpreted is hard.
How can I test this properly?
I can run a unit test that does a connect. Sadly, it will then process a life data stream. I can say I run the test for 30 or 60 seconds before disconnecting, but getting code ccoverage is impossible - I simply dont even comeclose to get all code paths EVERY ONCE PER DAY (error code paths are rarely run).
I also can not really assert every result. Depending on the time of the day we talk of 20.000 data callbacks per second - all of which are not relly determined good enough to validate each of them for consistency.
Mocking? Well, that would leave me testing an empty shell of myself because the code handling the events basically is the to be tested case, and in many cases we talk here of a COMPLEX c level structure - hard to have mocking frameworks that integrate from Csharp to C++
Anyone any idea? I am short on giving up using unit tests for this part of the application.
Unit testing is good, but it shouldn't be your only weapon against bugs. Look into the difference between unit tests and integration tests: it sounds to me like the latter is your best choice.
Also, automated tests (unit tests and integration tests) are only useful if your system's behavior isn't going to change. If you're breaking backward compatibility with every release, the automated tests of that functionality won't help you.
You may also want to see a previous discussion on how much unit testing is too much.
Does your external data source implement an interface -- or can you using a combination of an interface and a wrapper around the data source that implements the interface decouple your class under test from the data source. If either of these are true, then you can mock out the data source in your unit tests and provide the data from the mock instance.
public interface IDataSource
{
public List<DataObject> All();
...
}
public class DataWrapper : IDataSource
{
public DataWrapper( RealDataSource source )
{
this.Source = source;
}
public RealDataSource Source { get; set; }
public List<DataObject> All()
{
return this.Source.All();
}
}
Now in your class under test depend on the interface and inject an instance, then in your unit tests, provide a mock instance that implements the interface.
public void DataSourceAllTest()
{
var dataSource = MockRepository.GenerateMock<IDataSource>();
dataSource.Expect( s => s.All() ).Return( ... mock data ... );
var target = new ClassUnderTest( dataSource );
var actual = target.Foo();
// assert something about actual
dataSource.VerifyAllExpectations();
}