public class A {
public List<Model> getModels() {
List<Model> models = (some logic to find all models...)
models.forEach(model -> doSharedLogic(model));
}
public Model getModel(int id) {
Model model = (some logic to find Model by Id...)
doSharedLogic(model);
}
private void doSharedLogic(Model model) {
// manipulations with model...
}
}
Let's say I have the code above. I want to unit test public API (getModels and getModel methods). They use shared logic extracted into separate method doSharedLogic().
Question: How to correctly test those two methods if basically logic is completely the same?
**My assumptions: **
test getModel method with testing of all possible results for doSharedLogic();
do same for getModels();
But it's going to cause duplication of code in tests.
If I just test doSharedLogic as part of one of those public methods(for example: getModel()), I can't be sure that somebody won't come later, change something and break code in second method(getModels()) by removing shared logic for example
My assumptions: test getModel method with testing of all possible results for doSharedLogic();do same for getModels();
I would test each method for what they do and avoid duplication.
You have getModel() which gets a single instance. Test it for cases related to getting one instance including edge cases such as not found. If this code is also doing data transformation, then here is where I would test that the data is correct after the transformation, probably using a mock to inject data.
You have getModels() which gets multiples - all of them probably if it doesn't take some query string. Test it for cases that return multiple models, including the single or empty case. As this code is just calling getModel() under the covers, you should not reproduce any transformation logic tests and focus on testing the additional logic of "get many".
If you are really worried about someone changing the lgoic of getModels() later to not call getModel(), I would put that in comments in getModel() so that future editors know that if they remove that dependency they may need to add additional tests.
I would definitely not add a bunch of duplicative data transformation tests in both.
Related
I've designed a very simple disk based hash table. I've already tested it and the number of collisions is theoretically correct, but the test involved adding a field to the class that is incremented when there is a collision during the retrieval of an entry and checking at the end that the number of collisions is conformant. This counter is completely useless in the real class, so I'm asking if there is a smarter way to test the class without adding fields that are not needed outside JUnit tests. What is the best practice in this case?
More specifically, I can write a mock-up of my class:
public class HashTable {
//some fields here
int collisions_counter = 0; //this is only needed for testing! useless otherwise
//some methods here
public TableEntry get(Key key) {
//code to find the entry
if (collisions)
collisions_counter++;
//code to return the entry
}
}
This is very messy because if I want to change the collision resolution strategy or the hash function I need to add manually the field to the class and rewrite the logic to count the collisions, test the class and then remove the field because I don't need it in the final working class.
What if you were to use dependency injection? As far as I understand it, your hash table algorithm depends on disk operations. I don't know your solution, but I assume you write or read from the disk. If you abstract these operations away (e.g. by using an interface), you can inject the dependecy into your hash table solution (e.g. through the constructor). In the main code, you can inject the real disk based implementation. But when you test it, you can inject a mock (either your own mock or one from a library like Mockito) instead, and use the mock to assert the number of times it has been called.
I've problems with test methods which only get data from entity and assign it to DTO.
I passed empty DTO, and entity created by entityMother. The method works correctly, but I don't know how to make assertion for this. I think that creating assertion for each value/property of this DTO is not a right way to test it.
Why I need to test methods like this?
The methods that set data from entity to DTO has small formatting specyfic fields. Like splitting a string etc.
#Test
public void shouldSetAvailabilities() {
EditedTemplateShowDto editedTemplateDto = new EditedTemplateShowDto();
productTemplateEditService.getAndSetAvailabilities(editedTemplateDto, editedProduct);
//Here should be condition which check that the metod set data
}
I just need to check that the method didn't throw any errors, and none of fields has assigned null value.
The possible solutions are:
You may serialize your objects to JSON then compare the resulting strings. (Cleanest way)
Overriding a matching toString() then compare the resulting strings.
Put several assert condition using reflection (to check the variable name) in a test to check there are no any null value or not mapped value (Bad Practice).
Why I need to test methods like this?
First of all, you don't need to test anything. If you feel the code is extremely straight forward then I would advice to just invest your time into something else. Or perhaps write one sweeping test so at least you have code coverage (but IMO you'd be doing this more for the stats than actual quality of your product).
I just need to check that the method didn't throw any errors
That's easy! Just write a unit test that calls the method. If the method throws any exceptions, the test will fail. If you want to make your test method more intent-revealing, you could explicitly write it like:
try {
productTemplateEditService.getAndSetAvailabilities(editedTemplateDto, editedProduct);
} catch(Exception e) {
fail("Should not have thrown any exception");
}
But again, I'd only do this with methods I expect to throw exceptions (e.g. because they have exception paths or use other code/libraries that may throw exceptions). The default behavior of any unit test is to fail when it encounters an uncaught exception.
none of fields has assigned null value.
The JUnit way is to use assertNotNull in your test method on any fields you want to ensure are not null.
If you want a more generic approach there are additional libraries like assertj's hasNoNullFieldsOrProperties.
assertThat(editedTemplateDto).hasNoNullFieldsOrProperties();
Or you could write your own code using reflection like:
for (Field f : editedTemplateDto.getClass().getDeclaredFields())
assertNotNull(f.get(editedTemplateDto))
But I'd advice against this as it makes your test code harder to understand (and possibly brittle because reflection itself can be tricky)
The methods that set data from entity to DTO has small formatting
specyfic fields. Like splitting a string etc.
This makes a unit test meaningful: verify if the fields in the DTO are filled as expected. So don't just test on notNull but test on
Assert.assertEquals("FieldX has a wrong value","myexpectedValue",dto.getFieldX());
This way you test if the split logic behaves as expected.
Also test it with null values in all optional fields to verify you don't get NullPointerException.
I have a public method to test which calls a private method. This private method in turn calls a db using a variable that's provided from the public method. While unit testing I provide a dummy variable data to the public method, but its breaking as no record can be pulled from database with that dummy variable. How do I handle this? Right now, we have a try catch block for that private method call and the test always fails. As long as it doesn't give an error, we are passing the test. Is that right approach?
I apologize if it doesn't make much sense, I am rather new to unit testing. Thanks.
You should mock the results from the database request. After all, a test should not be aware of the data in your DB.
Mockito can help you there.
Another solution would be to use an in-memory database like H2,and populate it before the test with the required data. You could use something like DBUnit to populate it.
These tests wouldn't be as unitary, but you could still use jUnit to do them.
I have a class which models FK relationship. It has 2 lists in it. These lists contains the column names of the Parent Table & the Child Table respectively. These lists are passes by the client to me. Now before creating my FK object, I think it is necessary to do following checks (in order):
Check if lists are not null.
Check if lists contains null.
If a list contains duplicates columns?
Size of both the lists are equal.
So you can see there will be total 7 checks. Is it OK to have so many checks?
If it is OK to have these many checks, is there any pattern to handle such cases (with high no. of validation checks)?
If it is not OK, then what should I do? Should I just document these conditions as part of contract & mention that API will produce nonsensical results if this contract is violated?
Edit : Basically, I am trying to takes these 2 lists & produce a Database specific Query. So, it is kind of important to have this object built correctly.
Like everybody says, it depends on you. There is no such fixed/standard guideline for this. But to make it simple, you must have to put all your validation logic in one place, so that it remains readable and easy to change.
A suggestion can be, as you said, all of your validation logic seems to be very business oriented..by which I mean the end user should not be bothered about your db configuration. Let assume your class name, FKEntity. So if you follow the entity concept then you can put the validation logic in FKEntity.validate() (implementing an interface Validatable) which will validate the particular entity...this is for those kind of validation logic which applies to all FKEntity type objects in same way. And if you need any validation logic that compares/process different FKEntity depending on each other (e.g. if there is one FKEntity with some value "x" then no other entity can have "x" as their values, if they do, then you can not allow the entire entity list to persist), then you can put the logic in your Service layer.
Inteface Validatable { void validate() throws InvalidEntityException; }
Class FKEntity implements Validatable {
//..
public void validate() throws InvalidEntityException {
//your entity specific logic
}
}
Class FKDigestService {
public digestEntities() {
try {
for(FKEntity e : entityList)
e.validate();
//your collective validation logic goes here
} catch (EntityValidationException e) {//do whatever you want}
}
}
This will give you two advantages,
Your entity specific validation logic is kept in a single place (try to think most of the logic as entity specific logic)
Your collective logic is separated from entity logic, as you can not put these logic in your entity since these logic is only applicable when there is a collection of FKEntity, but not for single entity...it is business logic, not validation logic
I depends on you. There is no real argument against many checks. If your are developing an API, this can be very useful for other programmers. And it will make your own program more reliable.
I think the important point is, that you do your checks at one single point. You must have a clean and simple interface for your API. In this interface, it is ok to make checks. After these checks you could be sure that everything works.
What happens if you leaf the checks away? Will an exception be thrown somewhere or will the program just do something? If the program will just work and do something unpredictable, you should provide checks or things will begin to get strange. But if an exception will be thrown anyway, (I think) you can leaf the checks away. I mean, the program will get an exception anyway.
This is complex problem, so solution should be simplest possible to do not make it even more complicated and less understandable.
My approach would be:
some public method wrapping private method named something like doAllNeededListsValidationInFixedOrder() in which I'd create another private methods - each for every needed validation.
And ofc writing method like doAllNeededListsValidationInFixedOrder should be follow by some solid javadoc, even though it's not public.
If you want to go for pattern - the solution wouldn't be so straightforward. Basic thing to require checks in given order is to create lots or classes - every one for state telling that object is after one check, before another.
So you can achieve this with State pattern - treating every check as new state of object.
OR
You can use something like Builder pattern with forced order of methods invoked to create object. It is basically using a lot of interfaces to have every single (building) method (here validating) fired from different interface, to control order of them.
Going back to begining - using simple, well documenented and properly named method, that hides validating methods set, seems better for me.
If it is OK to have these many checks, is there any pattern to handle such cases (with high no. of validation checks)?
These checks become trivial if tackled from a data conversion point of view.
List from a client is actually any list of any possible elements
List from a client is to be converted to a well defined list of not duplicating not null elements
This conversion can be decomposed into several simple conversions ToNonNull, ToNonNullList, ToNonDuplicatingList
The last requirement is essentially conversion from two lists to one list of pairs ToPairs(ListA, ListB)
Put together it becomes:
ParentTableColumns = List1FromClient.
ToNonNull.
ToNonNullList.
ToNonDuplicatingList
ChildTableColumns = List2FromClient.
ToNonNull.
ToNonNullList.
ToNonDuplicatingList
ParentChildColumnPairs = List.
ToPairs(ParentTableColumns, ChildTableColumns)
If data from client is valid then all conversions succeed and valid result is obtained.
If data from client is invalid then one of the conversions fails and produces an error message.
So I have the bellow method which I want to perform a unit test on.
public List<Project> getProjects(Task task) {
Criteria<Project> criteria = this.myRepository.getCriteria(Project.class);
criteria.add(Comparison.eq("order", task.getOrder()));
criteria.addOrder(Order.asc("projectNumber"));
return this.myRepository.findList(Project.class, criteria);
}
So it actually gets the task object(It is a JPA model object) and goes throw the project table and finds all the projects which have this project's orders. Order is common in both tables.
Anyways, query itself is not that imp. It queries db and returns some data. Now my problem how can I perform a unit test on this with easymock?
#Test
public void testGetProjects() throws Exception {
myRepository = new CreateMyRepositoryWrapper(); --> This is a class which just returns the entityManger. but here we can consider this as a pojo.
Task task = EasyMock.createNiceMock(Task.class);
Order bom = EasyMock.createNiceMock(Order.class);
Project project= EasyMock.createNiceMock(Project.class);
project.setProjectName("project"); ------> Can I call a seeter on a mocked object?
project.setProjectNumber("1");
EasyMock.replay(project);
List projects= new ArrayList(Arrays.asList(project));
bom.setProjects(projects); ------------> Does it make sense to do this?
EasyMock.expect(task.getOrders()).andReturn(bom);
TestClass instance = new TestClass();
instance.setMyRepository(myRepository);
EasyMock.replay(task,bom);
instance.getProjects(task);
}
So this passes the test case. But I am not sure with all those mocking what I am actually testing.. Because it just shows that those methods are being called. But since they are mocked I am not sure if I can use assertEquals or not and even if I can I am getting an exception cuz I have to add more to the above code I think.
So my question: For the method mentioned what should be the proper unit test case?
Thanks.
I think you have this mocking backwards. Mock myRepostory, then set up the myRepository mock to return a Criteria object and to return a project list when that Criteria object is passed to findList.
Task, Order and Project can probably just be instantiated.
Now, instance.getProjects(task) will return something. You can check to make sure that thing that got returned is the same thing you said should be returned from findList. Now you've actually tested something, albeit nothing particularly interesting.
You probably want to validate that the criteria object was set up correctly before it was passed to findList. To do that, you either have to make criteria a mock, then you can set up your expectations for what methods are called. The tricky part here is that Hibernate Restriction classes do not have a non-default equals implementation, so you have to write your own matcher to check that the Restrictions being passed to the criteria are the same (functionally) as the Restrictions you expect.
Another possibility is to set up criteria as an actual Criteria object. (You still set up your myRepository mock to return it.) Then, after the function is called, you can check the contents with some substring matching on the toString() method or any other ways you know to inspect the Criteria object.
A final (unit test) possibility is to not use a mocking framework for the Criteria object, but some hand-coded one that you write that allows you to inspect all of the Restrictions that were added to it.
All of this makes a good case for this method actually being tested with integration testing instead. You wind up doing a lot of work to verify some not very interesting things and your tests can become quite brittle if you try to refactor the code. (I've done it myself, so I speak from experience.)