How to test methods efficiently with JUnit - java

My first method is simple, its just a toString which outputs 3 class specific fields
public String toString(){
return String.format("%s/%s/%s",street,city,postcode);
}
In JUnit it gives me this to form the tests on, I am unsure how to do this efficiently.
#Test
public void testToString() {
System.out.println("toString");
Address instance = null;
String expResult = "";
String result = instance.toString();
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
I have done lots of research on JUnit and understand the concept of testing but can't quite get my head around how to do it with my code. Also how would I test this method efficiently, this is a method in a subclass which is the abstract method in the parent class
#Override
int getDiscountRate() {
return this.companyDiscount;
}
It gives me this to test
#Test
public void testGetDiscountRate() {
System.out.println("getDiscountRate");
BusinessOrganisationDetails instance = null;
int expResult = 0;
int result = instance.getDiscountRate();
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}

This looks good. Of course, you need to instanciate the instance variables, else it will result in a NullPointerException.
Here, how it could look like in the end:
#Test
public void testToString() {
System.out.println("toString");
Address instance = new Address();
instance.setStreet("Somestreet");
instance.setCity("Somecity");
instance.setPostcode("12345");
String expResult = "SomestreetSomecity12345";
String result = instance.toString();
assertEquals(expResult, result);
}
And the other test:
#Test
public void testGetDiscountRate() {
System.out.println("getDiscountRate");
BusinessOrganisationDetails instance = new BusinessOrganisationDetails();
instance.setCompanyDiscount(50);
int expResult = 50;
int result = instance.getDiscountRate();
assertEquals(expResult, result);
}

Related

I am trying to write a Junit Test for this method, for context I have included a current test I have

I am trying to test the getOrGenerateID() method below in the generateClass class. I am struggling with writing a test that will test the logic of the method. I believe my current test as it is does not ensure coverage of all logic in the method
public class GenerateId {
static final Map<String,Object> map = new HashMap();
public static String getOrGenerateID() {
if (map.containsKey("TestMapKey")) { //check if map has a key
return map.get("TestMapKey"); // return the value for the key
}
else {
String newUId = "newID";
map.put("TestMapKey", newUId);
return newUId;
}
}
}
This is the Unit test I have written so far:
public void getOrGenerateIDTest() {
map.put("TestMapKey", "TestMapValue");
String newID = getOrGenerateID();
Assertions.assertTrue(map.containsKey("TestMapKey"));
Assertions.assertEquals("TestMapValue", map.get("TestMapKey");
}

JMockit Mock an object inside while loop

I have a below test class method that I am writing a test for.
public String doSomething(Dependency dep) {
StringBuilder content = new StringBuilder();
String response;
while ((response = dep.get()) != null) {
content.append(response);
}
return content.toString();
}
Below is the test case I have. Basically I want the Dependency#get() method to return "content" in the first iteration and null in the second.
#Test
void test(#Mocked Dependency dep) {
new Expectations() {
{
dep.get();
result = "content";
times = 1;
}
};
Assertions.assertEquals("content", testSubject.doSomething(dep));
}
However this results in JMockit throwing Unexpected invocation to: Dependency#get() error. If I remove the times field, my test runs in a forever loop.
How can I test this method?
So I found out that JMockit apart from the result paramater can also set a returns(args...) method to which we can pass a series of arguments that it will expect sequentially. So modifying the test to this worked for me.
#Test
void test(#Mocked Dependency dep) {
new Expectations() {
{
dep.get();
returns("content", null);
times = 2; // limiting to mock only twice as only 2 values are provided in returns
}
};
Assertions.assertEquals("content", testSubject.doSomething(dep));
}

How to throw exception for a local object method call?

MyCode:
class LocalClass{
public getNumber(){
retunr 5;
}
}
class AnotherLocalClass{
public static getNumber(){
retunr 10;
}
}
public class A{
public int methodAa(Boolean flag, int paramValue){
return methodA(flag, paramValue);
}
private int methodA(Boolean flag, int paramValue){
int returnValue = 0;
try{
if(flag){
LocalClass localVariable = new LocalClass();
returnValue = localVariable.getNumber() + paramValue;
} else{
returnValue = AnotherLocalClass.getNumber() + paramValue;
}
return returnValue;
}catch(Exception e){
e.printStackTrace();
return 0;
}
}
}
public class ATest{
#InjectMocks
A a;
public void methodATest(){
//need help to write here
}
}
LocalClass and AnotherLocalClass are classes that contains a method that returns a value.
getNumber in AnotherLocalClass is a static method.
Class A is the main class for which I am writing ATest class.
I can only write code in methodATest. And cannot change anything in LocalClass, AnotherLocalClass or class A.
I want to write methodATest such that methodA throws an exception.
My mockito version is 1.19.10 and it cannot be changed.
And also I cannot use PowerMockito or any other new dependency.
What exceptions do you expected to occur on your code? Which parameter values will cause the exceptions? In those cases, what is the return value that you're expecting?
When you get the answers for those questions, then you gonna have to set the conditions for the exception to happen. Then your code is gonna look something like this:
public class ATest{
A a = new A();
#Test
public void methodATest(){
Boolean flag = ?;
int paramValue = ?;
int expectedReturnValue = ?;
int returnValue = a.methodAa(flag, paramValue);
assertEquals(expectedReturnValue, returnValue);
}
}
Look out for the mock method. We usually use it when we need to set a class that we don't exactly want it to run it's methods, so we mock then to return something that we need for our test to work.
You can learn more about tests with this tutorial: https://www.vogella.com/tutorials/JUnit/article.html#junittesting
----[Edit]----
If you wanted to mock the LocalClass, you were gonna need to do something like this:
#PrepareForTest({LocalClass.class, A.class})
#RunWith(PowerMockRunner.class)
public class ATest{
A a = new A();
#Test
public void methodATest(){
PowerMockito.mockStatic(LocalClass.class);
PowerMockito.when(LocalClass.getNumber()).thenThrow(new Exception());
...
}
}
But, the getNumber() method should be static for it to work.
And, since you can not use PowerMockito, it's not possible to mock the class.
----[Edit]----
#PrepareForTest({AnotherLocalClass.class, A.class})
#RunWith(PowerMockRunner.class)
public class ATest{
A a = new A();
#Test
public void methodATest(){
PowerMockito.mockStatic(AnotherLocalClass.class);
PowerMockito.when(AnotherLocalClass.getNumber()).thenThrow(new Exception());
a.methodAa(...);
...
}
}
But again, since static method belongs to the class, there is no way in Mockito to mock static methods.

Mock method to return a value only when passed any *non-null* object of a given class

I'm using Mockito to mock a method to return a Date when given a Date.
when(supplier.calculateDeliveryDate(any(Date.class)))
.thenReturn(supplierDeliveryDate);
However, I only want it to return the supplierDeliveryDate when it is passed a non-null Date object.
When passed null, it should return null.
Is this possible? How can I do it?
Use ArgumentMatchers.isNull() matcher.
when(supplier.calculateDeliveryDate(any(Date.class)))
.thenReturn(supplierDeliveryDate);
when(supplier.calculateDeliveryDate(isNull()))
.thenReturn(null);
You could use an anonymous inner class:
// unit test
public OrderServiceTest {
// instance of class-under-test
private OrderService instance;
// stub value
private Date supplierDeliveryDate = new Date();
// mock as an anonymous inner class
private Supplier supplier = new Supplier() {
public Date calculateDeliveryDate(Date input) {
if (input == null) {
return null;
}
else {
return supplierDeliveryDate;
}
}
};
#Before
public void setUp() {
instance = new OrderService();
// dependency injection
instance.setSupplier(supplier);
}
#Test
public void testOrderHappy() {
// SETUP
Date orderDate = new Date();
// CALL
Date result = instance.order(orderDate);
// VERIFY
assertTrue(supplierDeliveryDate == result);
}
#Test
public void testOrderNull() {
// SETUP
Date orderDate = null;
// CALL
Date result = instance.order(orderDate);
// VERIFY
assertNull(result);
}
}
But you should really wonder why you need this kind of behavior.
If you write a well defined test case then you should know exactly how often, and with which arguments, your mock is called. If so, then you can just stub the expected calls instead of wiring your mock with conditional behavior.
Note that is is useful if your test is as 'sharp' as possible. If a different number of calls hits your mock than expected, or with different arguments, then the test should fail.
You can use helper method:
public static <T> void validateAndMock(Supplier<T> ongoingStubbing, T mockedResponse) {
if (mockedResponse != null) {
when(ongoingStubbing.get()).thenReturn(mockedResponse);
}
}
And then call:
validateAndMock(() -> supplier.calculateDeliveryDate(any(Date.class)), supplierDeliveryDate);

Mocking behavior of an object created using static factory method

I am refactoring a Hibernate mapped object Gadget to remove getIntFieldValue and setIntFieldValue and changing my code to retrieve that value from a DAO object, which is created using a Factory and to which a Gadget is passed.
public class GadgetPropertyAccessFactory {
public static GadgetPropertyDAO getGadgetPropertyDAO(Session dbSessn){
if(getSomeBooleanFromDB(dbSessn)) {
return new TrueImplGadgetPropertyDAO();
} else {
return new FalseImplGadgetPropertyDAO();
}
}
...
The test code looks like this:
//this mocks a Gadget
Gadget gadget = createGadget();
//this is to be replaced
when(gadget.getIntFieldValue()).thenReturn(2);
DoerClass doerClass = new DoerClass(null, gadget);
List<Result> doerResults = doerClass.produceResults();
for (Result doerResult : doerResults) {
//...
}
The DoerClass looks something like this
Session dbSessn;
Gadget gadget;
public DoerClass(Session dbSessn, Gadget gadget) {
this.dbSessn = dbSessn;
this.gadget = gadget;
}
public List<Result> produceResults() {
//this is to be replaced
int intFieldValue = this.gadget.getIntFieldValue()
//with
//GadgetPropertyDAO gadgPropDAO = GadgetPropertyAccessFactory.getGadgetPropertyDAO(this.dbSessn);
//int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
//generate List<Result> based on intFieldValue
}
My problem is that before I was able to conveniently mock what getIntFieldValue will return in produceResults but now that I am using a statically returned DAO, I do not know if it is possible to mock what GadgetPropertyDAO.getDeviceIntFieldValue(this.gadget) will return.
Is a mock possible without changing my method signatures (API)?
I agree with Tom G: Mockito and dependency injection (and arguably Java itself) are really designed for instances much more than static methods—it's the only way to take advantage of Java's polymorphic advantages. If you switch to making your factory an instance, it would look like this:
public class GadgetPropertyAccessFactory {
public GadgetPropertyDAO getGadgetPropertyDAO(Session dbSessn){
if(getSomeBooleanFromDB(dbSessn)) {
return new TrueImplGadgetPropertyDAO();
} else {
return new FalseImplGadgetPropertyDAO();
}
} // ...
}
public class DoerClass {
Gadget gadget;
Session dbSessn;
// Sets default implementation. Constructor injection would also work.
GadgetPropertyAccessFactory gpaFactory = new GadgetPropertyAccessFactory();
public DoerClass(Session dbSessn, Gadget gadget) {
this.dbSessn = dbSessn;
this.gadget = gadget;
}
public List<Result> produceResults() {
GadgetPropertyDAO gadgPropDAO =
gpaFactory.getGadgetPropertyDAO(this.dbSessn);
int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
// ...
}
}
// in your test
DoerClass doerClass = new DoerClass(null, gadget);
GadgetPropertyAccessFactory mockFactory =
Mockito.mock(GadgetPropertyAccessFactory.class);
doerClass.gpaFactory = mockFactory;
// ...
Another option is to live with and manage your testing gap:
public List<Result> produceResults() {
return produceResultsInternal(gpaFactory.getGadgetPropertyDAO(this.dbSessn));
}
/** Visible only for testing. Do not call outside of tests. */
List<Result> produceResultsInternal(GadgetPropertyDAO gadgPropDAO) {
int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
// ...
}
...which then allows you to test against produceResultsInternal with a mock, which gets you 80% tested with 20% of the grief.

Categories