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.
Related
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.
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.
A system handles two types of resources. There are write and delete APIs for managing the resources. A client (user) will use a library API to manage these resources. Each resource write (or create) will result in updating a store or a database.
The API would look like:
1) Create Library client. The user will use the returned client to operate on the resources.
MyClient createClient(); //to create the client
2) MyClient interface. Providing operations on a resource
writeResourceType1(id);
deleteResourceType1(id);
writeResourceType2(id);
deleteResourceType2(id);
Some resources are dependent on the other. The user may write them out-of-order (might write a resource before writing its dependent). In order to prevent the system from having an inconsistent state, all changes (resource updates) will be written to a staging location. The changes will be written to the actual store only when the user indicates he/she has written everything.
This means I would need a commit kind of method in the above MyClient interface. So, access pattern will look like
Client client = provider.createClient();
..
client.writeResourceType1(..)
client.writeResourceType1(..)
client.deleteResourceType2(..)
client.commit(); //<----
I'm not comfortable having the commit API in the MyClient interface. I feel it is polluting it and a wrong it is a wrong level of abstraction.
Is there a better way to handle this?
Another option I thought of is getting all the updates as part of a single call. This API would act as a Batch API
writeOrDelete(List<Operations> writeAndDeleteOpsForAllResources)
The downside of this is this the user has to combine all the operations on their end to call this. This is also stuffing too much into a single call. So, I'm not inclined to this approach.
While both ways that you've presented can be viable options, the thing is that at some point in time, the user must somehow say: "Ok, these are are my changes, take them all or leave them". This is exactly what commit is IMO.
And this alone makes necessary some kind of call that must present in the API.
In the first approach that you've presented its obviously explicit, and is done with commit method.
In the second approach its rather implicit and is determined by the content of the list that you pass into writeOrDelete method.
So in my understanding, commit must exist somehow, but the question is how do you make it less "annoying" :)
Here are couple of tricks:
Trick 1: Builder / DSL
interface MyBuilder {
MyBuilder addResourceType1(id);
MyBuilder addResourceType2(id);
MyBuilder deleteResourceType1/2...();
BatchRequest build();
}
interface MyClient {
BatchExecutionResult executeBatchRequest(BatchRequest req);
}
This method is more or less like the second method, however it has a clear way of "adding resources". A single point of creation (pretty much like MyClient not, just I believe that eventually it will have more methods, so maybe its a good idea to separate. As you stated: "I'm not comfortable having the commit API in the MyClient interface. I feel it is polluting it and a wrong it is a wrong level of abstraction")
Additional argument for this approach is that now you know that there is a builder and its an "abstraction to go" in your code that uses this, you don't have to think about passing a reference to the list, think about what happens if someone calls stuff like clear() on this list, and so on and so forth. The builder has a precisely defined API of what can be done.
In terms of creating the builder:
You can go with something like Static Utility class or even add a method to MyClient:
// option1
public class MyClientDSL {
private MyClientDSL {}
public static MyBuilder createBuilder();
}
// option 2
public interface MyClient {
MyBuilder newBuilder();
}
References to this approach: JOOQ (they have DSL like this), OkHttp that have builders for Http Requests, Bodies and so forth (decoupled from the OkHttpClient itself).
Trick 2: Providing an execution code block
Now this can be tricky to implement depending on what kind of environment do you run in,
but basically an idea is borrowed from Spring:
In order to guarantee a transaction while working with databases they provide a special annotation #Transactional that while placed on the methods basically says: "everything inside the method is running in transaction, I'll commit it by myself so that the user won't deal with transactions/commits at all. I'll also roll back upon exception"
So in code it looks like:
class MyBusinessService {
private MyClient myClient; // injected
#Transactional
public void doSomething() {
myClient.addResourceType1();
...
myClient.addResourceType2();
...
}
}
Under the hood they should maintain ThreadLocals to make this possible in multithreaded environment, but the point is that the API is clean. The method commit might exist but probably won't be used at the most of the cases, leaving alone the really sophisticated scenarios where the user might really "need" this fine-grained control.
If you use spring/ any other containter that manages your code, you can integrate it with spring (the technical way of doing this is out of scope of this question, but you get the idea).
If not, you can provide the most simplistic way of it:
public class MyClientCommitableBlock {
public static <T> T executeInTransaction(CodeBlock<T> someBlock)
builder) {
MyBuilder builder = create...;
T result = codeBlock(builder);
// build the request, execute and commit
return result;
}
}
Here is how it looks:
static import MyClientCommitableBlock.*;
public static void main() {
Integer result = executeInTransaction(builder -> {
builder.addResourceType1();
...
return 42;
});
}
// or using method reference:
class Bar {
Integer foo() {
return executeInTransaction(this::bar);
}
private Integer bar(MyBuilder builder) {
....
}
}
In this approach a builder while still defining precisely a set of APIs might not have an "explicit" commit method exposed to the end user. Instead it can have some "package private" method to be used from within the MyClientCommitableBlock class
Try if this suits you
Let us have a flag in staging table with column named status
Status Column values
New : Record inserted by user
ReadyForProcessing : Records ready for processing
Completed : Records processed and updated in Actual Store
Add this below method instead of commit(), and once user invokes this method/service, pick up the records which are for this user and which are in status: New and post it into the Actual Store from the staging location
client.userUpdateCompleted();
There is another option as well let us take out the client intervention by giving client.commit(); or client.userUpdateCompleted(); and instead we can have a batch process using Scheduler which runs at specific intervals which scans the Staging Table and populates the meaningful and user update completed records into the Actual Store
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.)