So for my programming class, we are supposed to make a Junit test for one of our classes that inherits from an abstract class. I've just been really confused on writing Junit tests since I don't feel like there's enough examples online. My first question is, do we test getters and setters? My professor instructed us to "select all" the methods when setting up our test, but on a website she asked us to read, they advised not to test getters and setters because JVM already has testers for them. My second and most important question is can you test an entire constructor? My code below basically has an undergrad student inheriting from an abstract student class. I'm assuming I should test to make sure that the undergrad student is in fact an undergrad student and not a master student, but I don't know how to exactly test an entire constructor. Any tips would be greatly appreciated!!
public abstract class AbstractStudent {
/**
* First name of a student.
*/
private String myFirstName;
/**
* Last name of a student.
*/
private String myLastName;
/**
* Student 9-digit ID.
*/
private String myID;
/**
* Number of credit hours completed by a student.
*/
private int myCreditHours;
/**
* Current student GPA.
*/
private double myGPA;
/**
* Student gender.
*/
private Gender myGender;
/** Student date of birth.
*
*/
private Date myBirth;
/**
* Private constructor to prohibit default instantiation.
*/
/**
* #param theFirstName Adds the first name into the constructor
* #param theLastName Adds the last name into the constructor
* #param theID Adds the ID into the constructor
* #param theCreditHours Adds the credit hours into the constructor
* #param theGPA Adds the GPA into the constructor
* #param theGender Adds the gender into the constructor
* #param theBirth Adds the birth into the constructor
*/
public AbstractStudent(final String theFirstName, final String theLastName,
final String theID, final int theCreditHours, final double theGPA,
final Gender theGender, final Date theBirth) {
myFirstName = theFirstName;
myLastName = theLastName;
myID = theID;
myCreditHours = theCreditHours;
myGPA = theGPA;
myGender = theGender;
myBirth = new Date(theBirth.getTime());
}
And the UndergradStudent class:
public class UndergradStudent extends AbstractStudent {
/**
* Student status.
*/
private StudentStatus myStatus;
/**
* Parameterized constructor - constructors a Student object.
* #param theFirstName is a string representing the first name of a student, != null
* #param theLastName is a string representing the last name of a student, != null
* #param theID is a string of 9 characters representing student ID
* #param theCreditHours is an integer number >=0 representing number of credit hours
* taken by a student
* #param theGPA is a double number representing GPA, a GPA must be >= 0 and <= 4.0
* #param theStatus is a string representing student status, != null
* #param theGender is a character representing student gender, != null
* #param theBirth is a date representing student birth date; a student cannot be younger
* than 10 years old
* #custom.post Student object constructed; if invalid parameters passed,
* student is in an invalid state.
*/
public UndergradStudent(final String theFirstName, final String theLastName,
final String theID, final int theCreditHours, final double theGPA,
final StudentStatus theStatus, final Gender theGender,
final Date theBirth) {
super(theFirstName, theLastName, theID, theCreditHours, theGPA, theGender, theBirth);
myStatus = theStatus;
}
I can't really comment on the intention of your professor but when writing unit tests you are aiming to test single units of functionality. Most developers consider testing basic POJO behaviour where a get method returns a constructor property as redundant, however if you are writing getter/setter methods which are stateful they are worth testing.
One way you could test the whole constructor of UndergradStudent is to construct an instance either as a private final variable or using JUnit's #BeforeClass annotation and writing a separate #Test for each property getter.
Related
I'm trying to figure out how to get the relativeAtomicMass from one class named ChemicalElement onto another called MolarMass in which I try to figure out the atomicmass of an element given it's symbol then find out a compound mass. I'm not sure how to return a double, I tried using a toString to do it since that's what a tutor taught me to do but I'm not sure if it's the correct way that my teacher wants me to do it. I know I need to get the relativeAtomicMass onto MolarMass to finish the assignment but i'm stuck at the moment. Heres the code for my assignment:
package chemical;
public class ChemicalElement {
// Properties (fields/variables): This time we leave give them default visibility, which gives
// other classes in the same package (i.e. the same directory) full access to them, for brevity.
/** The number of protons */
int atomicNumber;
/** 1-3 letter IUPAC symbol */
String symbol;
/** Full name */
String name;
/** Relative atomic mass () */
double relativeAtomicMass;
/** Row in the periodic table */
int period;
/** Column in the periodic table */
int group;
// Actions (methods): For now we provide a constructor to initialize all fields.
/**
* Constructs a new ChemicalElement object with the given properties.
*
* #param atomicNumber the number of protons
* #param symbol the IUPAC symbol
* #param name the full name
* #param relativeAtomicMass the average atomic mass relative to carbon-12
* #param period the row in the periodic table
* #param group the column in the periodic table
*/
public ChemicalElement(int atomicNumber, String symbol, String name, double relativeAtomicMass,
int period, int group) {
this.atomicNumber = atomicNumber;
this.symbol = symbol;
this.name = name;
this.relativeAtomicMass = relativeAtomicMass;
this.period = period;
this.group = group;
}
public String toString()
{
return name;
}
}
package chemical;
import java.net.URL;
import java.util.Scanner;
import java.util.Arrays;
public class MolarMass {
public static void main(String[] compoundTokens) throws Exception {
ChemicalElement[] elements = readElementData();
//System.out.printf("%.6f%n", compoundmass(elements, compoundTokens));
System.out.println(Arrays.toString(elements));
}
/**
* Loads data about all chemical elements into an array.
*
* #return an array containing references to objects describing all 118 chemical elements
* #throws Exception if anything goes awry (we only know how to pass the buck)
*/
private static ChemicalElement[] readElementData() throws Exception {
ChemicalElement[] elements = new ChemicalElement[119];
Scanner dataFile =
new Scanner(new URL("http://jeff.cis.cabrillo.edu/datasets/elements").openStream());
while (dataFile.hasNext()) {
// Example line: 1 H Hydrogen 1.008 1 1
int atomicNumber = dataFile.nextInt();
elements[atomicNumber] = new ChemicalElement(atomicNumber, dataFile.next(), dataFile.next(),
dataFile.nextDouble(), dataFile.nextInt(), dataFile.nextInt());
}
return elements;
}
/**
* Determines the molar mass of a compound.
*
* #param elements an array containing references to objects describing all 118 chemical elements
* #param tokens a compound formula
* #return the molar mass of the given compound
*/
// private static double compoundMass(ChemicalElement[] elements, String[] tokens) {
// TODO
/**
* Determines the relative atomic mass of an element, given its symbol.
*
* #param elements an array containing references to objects describing all 118 chemical elements
* #param symbol the symbol of the element in question
* #return the relative atomic mass of the given element
*/
// private static double relativeAtomicMass(ChemicalElement[] elements, String symbol) {
// TODO
}
Also i'd imagine that once I get the relative atomic mass onto molarmass it would be easy to fill out the code for relativeatomicmass but how would I use that to create compounds?
Thanks any help would be appreciated.
This is a small Java application that is designed to calculate a departments total monthly expenses by adding the amounts paid to all the employees in that department. The departments employees are arranged in a hierarchy, which this app seeks to take into account with how it arranges objects.
I'm new to JUnit and unit testing. I'm attempting to run a test comparing my actual total to an expected total. However, I'm getting a number of error(detailed in the source code below).
Note I'm using: Windows 8.1, Java SE 8, eclipse Luna, JUnit 4.
I have 1 main question, & 1 side questions:
Could you help me to understand what is causing these errors and what I can do to correct them?
I'm trying to improve my documentation style by moving from 'comments' to something a little more professional. Could this documentation be improved?
Thanks for taking a look.
Unit Test
package test;
import static org.junit.Assert.*;
import org.junit.Test;
import expenseApp.Developer; // The import expenseApp cannot be resolved
import expenseApp.Manager; // The import expenseApp cannot be resolved
import expenseApp.QATester; // The import expenseApp cannot be resolved
/**
* TestClass evaluates a departments actual total expenses,
* by comparing them to a projected total.
* #author Reed
*/
public class TestClass {
/**
* testOne() compares a departments actual total expenses with a projected total of $2100.00.
* This departments employees create the following hierarchy:
* managerA <-- managerB <-- tester1 & dev1.
*/
#Test
public void testOne()
{
QATester tester1 = new QATester(); // Multiple markers at this line - QATester cannot be resolved to a type x2
Developer dev1 = new Developer(); // Multiple markers at this line - Developer cannot be resolved to a type x2
Manager managerB = new Manager(); // Multiple markers at this line - Manager cannot be resolved to a type x2
managerB.add(tester1);
managerB.add(dev1);
Manager managerA = new Manager(); // Multiple markers at this line - Manager cannot be resolved to a type x2
managerA.add(managerB);
assertEquals(managerA.getTotalExpenses(), 2100.00, 0.00);
fail("Not yet implemented"); // automatically generated, should I use this?
}
}
App
//Employee
package expenseApp;
/**
* Employee is the abstract superclass of Manager, QATester, and Developer.
* Employee declares public abstract double getExpenses().
* #author Reed
*/
public abstract class Employee
{
/**
* getExpenses() returns the monthly allocation amount of a Manager, Developer, or QATester object.
* #return a double values representing what the specified Employee is paid each month.
*/
public abstract double getExpenses();
}
// QATester
package expenseApp;
/**
* QA Testers warrant a monthly allocation of $500.00, per QA Tester.
* QATester extends Employee.
* #author Reed
*/
public class QATester extends Employee
{
/**
* getExpenses() returns a QA Testers monthly allocation amount.
* #return a double value of 500.00.
*/
#Override
public double getExpenses()
{
return 500.00;
}
}
// Developer
package expenseApp;
/**
* Developers warrant a monthly allocation of $1000.00, per Developer.
* Developer extends Employee.
* #author Reed
*/
public class Developer extends Employee
{
/**
* getExpenses() returns a Developers monthly allocation amount.
* #return a double value of 1000.00.
*/
#Override
public double getExpenses()
{
return 1000.00;
}
}
// Manager
package expenseApp;
import java.util.ArrayList;
/**
* Managers warrant a monthly allocation of $300.00, per Manager.
*
* A manager is at the top of a hierarchical relationship,
* in which one manager oversees employees such as developers,
* QA testers, & other managers. An employee's title is associated with
* an amount that type of employee is paid monthly.
* A compete hierarchy constitutes all the employees of a department.
* A departments expenses can be determined by adding the amounts
* paid to the employees in a hierarchy.
*
* Manager extends Employee.
*
* #author Reed
*/
public class Manager extends Employee
{
private ArrayList<Manager> managerList = new ArrayList<>();
private ArrayList<Employee> employeeList = new ArrayList<>();
/**
* Add() adds employees to a list.
* If the employee is a manager, managerList.
* Else, the employee is a developer or QA tester, employeeList.
* #param employee
*/
public void add(Employee employee)
{
if(employee instanceof Manager)
{
managerList.add((Manager) employee);
}
else
{
employeeList.add(employee);
}
}
/**
* getExpenses() returns a Mangers monthly allocation amount.
* #return a double value of 300.00.
*/
#Override
public double getExpenses()
{
return 300.00;
}
/**
* getTotalExpenses() adds the values in managerList and employeeList,
* calculating a departments total monthly expenses.
* #return the value of totalExpenses.
*/
public double getTotalExpenses()
{
double totalExpenses = 0.00;
for(Manager manager : managerList)
{
totalExpenses += manager.getTotalExpenses();
}
for(Employee employee : employeeList)
{
totalExpenses += employee.getExpenses();
}
return totalExpenses;
}
}
import expenseApp.Developer; // The import expenseApp cannot be resolved
This error means that Eclipse can't find the code for the class Developer. This problem is not related to JUnit or unit tests.
Make sure your build path contains the necessary JARs and projects.
Also, remove the fail() at the end of the test since you have now implemented the test.
documentation
A better way to document is to use variables:
double expected = 2100.0;
double maxDelta = 1e-6;
assertEquals(expected, managerA.getTotalExpenses(), maxDelta);
The variables explain what a value means. "2100" means nothing. "expected" communicates: That's the expected result.
You could use expectedDollars to say "this value is in dollars".
If you have only short pieces of code, don't document them. People can read the code to understand what is going on. But you can help them by adding methods with useful names:
Manager managerB = managerWithADevAndTester();
Manager managerA = createManagerFor( managerB );
or, if you prefer simple DSLs:
Manager managerB = createManagerFor(
new QATester(),
new Developer()
);
Manager managerA = createManagerFor( managerB );
Based on our comment discussion, it seems you wrote your unit tests in another Eclipse project. Typically tests are located within the same project, thus they benefit from having all the project classes on the classpath.
If you'd like to use a separate project, you'll need to edit the test project properties to tell Eclipse that you have a dependency on your main project.
The fail call at the end of the test case should be removed, that will always fail the test regardless of the assertion result on the line above.
Implement a class Student. For the purpose of this exercise, a student has a name and a total quiz score. Supply an appropriate constructor and methods getName(), addQuiz(int score), getTotalScore(), and getAverageScore(). To compute the latter, you also need to store the number of quizzes that the student took.
...
I am having an especially hard time with the scores and name. Do I add the scores to both the Student.java and the StudentTester.java files or only the tester? I cannot figure this out.
Here is my code:
/** A student has taken a number of quizzes and has an average score
based on the quizzes that were taken.
*/
public class Student
{
private String name;
private double totalscore;
private int numquiz;
}
// Constructs a student object with the name "MccStudent" and with zero total of quiz scores
public Student(String "mccStudent")
{
this.name = studentname;
numquiz = 0;
totalscore = 0;
}
public String getName()
{
return name;
}
// Adds the number of quizzes taken
public void addQuiz(double quizscore)
{
totalscore+=quizscore;
numquiz++;
}
// Returns the total quiz score
public double getTotalScore ()
{
return totalscore;
}
// Returns the avaerage grade
public double getAverageScore ()
{
return totalscore/numquiz;
}
}
/** Create a class to test the Student class.
*/
public class StudentTester
{
/**
Tests the methods of the Student class.
*/
public static void main(String[] args)
{
// Create an object
Student mccStudent = new Student();
mccStudent.addQuiz(100);
mccStudent.addQuiz(80);
mccStudent.addQuiz(95);
mccStudent.addQuiz(97);
System.out.println(mccStudent.getName());
System.out.println(mccStudent.getTotalScore());
// Display average quiz score
System.out.println(mccStudent.getAverage.Score());
}
}
First of all try to understand what Constructor is. Here is oracle documentation with nice examples: Constructor. Ill write simple example for you. Student is new Object that has String name attribute.
public class Student {
public String name; //name of student
public Student(String name) {//Constructor for student, receiving name when u create new object Student
this.name = name; //set received name to this public String name
}
/**
* When u call this method you will get inputed name from constructor
* so if u call Student stud = new Student("John");
* new Student("John") is constructor!
* with stud.getName(); you will get "John".
* This is called getter.
* #return name of student
*/
public String getName() {
return name;
}
}
There are some major issues here, for one the first brace is closed after declaring your instance variables, so the rest of the code for Student is out of scope. Remove the first close brace, and that should help that.
Another issue is the way you are using your constructor (the part that says public Student(String "mccstudents")). You need to providing a variable name there, and then whenever you make a new object, you pass in a string, and that will take the place of the variable name.
Not to sound like one of your teaches, you really shouldn't leave this to last minute To jump the gun on any number of people who will write a reply for this, this site is designed to help specific issues, not analyse the whole program.
Are there particular issues and concepts that you are not understanding that I can help with?
You add the fields to the class itself (Student.java).
Only code that performs tests should appear in the test class (StudentTester.java).
I have been given the exiciting job to add some javadoc to some code.
so here is my Q:
what is the right way to write javadoc for this constructor.
public Match(int MatchID, int MatchRound, int HomeTeamID, int GuestTeamID, boolean IsPlayed) {
this.isPlayed = IsPlayed;
this.matchID = MatchID;
this.matchRound = MatchRound;
this.homeTeamID = HomeTeamID;
this.guestTeamID = GuestTeamID;
}
I wouldn't write any, because it's obvious.
I would rename all the parameters to follow Java conventions, though.
Here is the formatted Javadoc:
/**
* Constructor for creating a new match.
* #param MatchID the id of the match
* #param MatchRound the round for the match
* #param HomeTeamID the id of the home team
* #param GuestTeamID the id of the guest team
* #param IsPlayed whether or not the match is played
*/
public Match(int MatchID, int MatchRound, int HomeTeamID, int GuestTeamID, boolean IsPlayed) {
In Eclipse you can just type /** above the constructor and it will generate the Javadoc template automatically.
I'm working with Mybatis 3.2.6 and implementing a custom resulthandler. I've done this before using a simple datatype parameter and have had no problems. This time around I need to pass in several arguments... The signature I'm using is
session.select(statement, parameter, handler);
For parameter I've created a simple POJO to easily send in what I need. It is as follows:
public class DifferenceParam {
private int current;
private int compare;
private String table;
private String comparator;
/**
* Constructor excluding comparator. Will default a value of
* "code" to compare content on, e.g., <br/>
* {#code select * from a minus select * from b where a.code = b.code } <br/>
* #param table
* #param current
* #param compare
*/
public DifferenceParam(String table, int current, int compare) {
this(table, "code", current, compare);
}
/**
* Constructor providing a specific column to compare on, e.g. <br/>
* {#code select * from a minus select * from b where a.[comparator] = b.[comparator] } <br/>
* #param table
* #param comparator
* #param current
* #param compare
*/
public DifferenceParam(String table, String comparator, int current, int compare) {
this.table = table;
this.comparator = comparator;
this.current = current;
this.compare = compare;
}
/** Appropriate setters and getters to follow **/
}
The handler implementation is irrelevant at the moment, because I get an exception well in advance... The query I'm executing is:
<select id="getCodeSetModifications" parameterType="DifferenceParam" resultType="Code">
select *
from
(
select * from ${param.table} where revision_seq = #{param.current}
minus
select * from ${param.table} where revision_seq = #{param.compare}
) a, ${param.table} b
where a.${param.comparator} = b.${param.comparator}
and b.revision_seq = #{param.compare}
</select>
Here is the interface as well
public List<Code> getCodeSetModifications(#Param("param") DifferenceParam param);
The problem I'm having is that execution via a mapper e.g.,
session.getMapper(DifferenceParam.class);
works just fine, but when I invoke through a select on the session I get the following exception.
Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'param' in 'class com.mmm.his.cer.cerval.uidifference.map.param.DifferenceParam'
Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'param' in 'class com.mmm.his.cer.cerval.uidifference.map.param.DifferenceParam'
I've debugged as far as I can go into Mybatis, but am having no luck.
Thanks in advance...
When you use session.getMapper(DifferenceParam.class);, mybatis looks for #Param annotation and uses it's value in query.
When you invoke session.select(statement, parameter, handler);, such mapping doesn't occur.
Try to add public DifferenceParam getParam() { return this; } to DifferenceParam to workaround this.
when the MyBatis query only have one param. Don't need #{param.} reference.
because it default use the only param.
so when u use ${param.table}, it actually using #{DifferenceParam.param.table}.
because it think the ${param.} inside of the #{DifferenceParam.}