Merge branch 'database_fixes' into 'master'

Merge database_fixes branch into master

See merge request cse1105/2018-2019/oopp-group-43/template!14
This commit is contained in:
Sem van der Hoeven
2019-03-16 13:50:44 +00:00
27 changed files with 790 additions and 508 deletions

View File

@@ -21,11 +21,9 @@ apply plugin: 'checkstyle'
apply plugin: 'application' apply plugin: 'application'
application { application {
mainClassName = 'greenify.client.Application' mainClassName = 'greenify.server.Application'
} }
//apply plugin: 'org.openjfx.javafxplugin'
tasks.withType(Checkstyle) { tasks.withType(Checkstyle) {
reports { reports {
html.destination rootProject.file("build/reports/checkstyle.html") html.destination rootProject.file("build/reports/checkstyle.html")
@@ -36,16 +34,32 @@ repositories {
mavenCentral() mavenCentral()
} }
//client bootjar allprojects {
bootJar { task hello {
baseName = 'gs-consuming-rest' doLast { task ->
version = '0.1.0' println "I'm $task.project.name"
}
}
} }
//server bootjar ////client bootjar
//bootJar {
// baseName = 'gs-consuming-rest'
// version = '0.1.0'
//}
//
////server bootjar
//bootJar {
// baseName = 'gs-rest-service'
// version = '0.1.0'
//}
bootJar { bootJar {
baseName = 'gs-rest-service' enabled = false
version = '0.1.0' }
jar {
enabled = true
} }
sourceCompatibility = 1.8 sourceCompatibility = 1.8

View File

@@ -1,12 +0,0 @@
# Sprint Review
## Main problems Encountered
We have no problems so far. Everyone arrives on time and does the tasks assigned to them.
## Adjustments from previous sprints
Since this is the first review, there are no previous sprints yet
## Adjustments for next sprint
- Keep up the good work!

View File

@@ -1,14 +0,0 @@
# Sprint Review
## Main problems Encountered
### Problem 1: Kristin left the group
Kristin does not continue CSE and left our group. We'll work with five people from now on.
## Adjustments from previous sprints
We created the backlog before the sprint, which helps making clear what we're working on.
## Adjustments for next sprint
- Group made out of five
- Backlogs ready on time

View File

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

1
src/.idea/gradle.xml generated
View File

@@ -8,6 +8,7 @@
<option name="gradleHome" value="$USER_HOME$/scoop/apps/gradle/current" /> <option name="gradleHome" value="$USER_HOME$/scoop/apps/gradle/current" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$/.." />
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/Client" /> <option value="$PROJECT_DIR$/Client" />
<option value="$PROJECT_DIR$/Common" /> <option value="$PROJECT_DIR$/Common" />

6
src/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

785
src/.idea/workspace.xml generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,11 +21,6 @@ public class Application extends javafx.application.Application {
launch(args); launch(args);
} }
// @Bean
// public RestTemplate restTemplate(RestTemplateBuilder builder) {
// return builder.build();
// }
@Override @Override
public void init() throws Exception { public void init() throws Exception {
springContext = SpringApplication.run(Application.class); springContext = SpringApplication.run(Application.class);
@@ -36,25 +31,9 @@ public class Application extends javafx.application.Application {
@Override @Override
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
fxmlLoader.setLocation(this.getClass().getClassLoader().getResource("fxml/sample.fxml")); fxmlLoader.setLocation(this.getClass().getClassLoader().getResource("fxml/sample.fxml"));
// fxmlLoader.setLocation(
// this.getClass().getClassLoader().getResource("fxml/dashboard.fxml")
// );
rootNode = fxmlLoader.load(); rootNode = fxmlLoader.load();
// rootNode = FXMLLoader.load(
// this.getClass().getClassLoader().getResource("fxml/sample.fxml")
// );
primaryStage.setTitle("GoGreen"); primaryStage.setTitle("GoGreen");
Scene scene = new Scene(rootNode); Scene scene = new Scene(rootNode);
// scene.getStylesheets().add(
// getClass().getResource("stylesheets/dashboardStyle.css").toExternalForm()
// );
primaryStage.setScene(scene); primaryStage.setScene(scene);
primaryStage.show(); primaryStage.show();
} }
@@ -63,14 +42,4 @@ public class Application extends javafx.application.Application {
public void stop() { public void stop() {
springContext.stop(); springContext.stop();
} }
// @Bean
// public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
// return args -> {
// User user = restTemplate.getForObject(
// "http://localhost:8080/user", User.class);
// log.info(user.toString());
//
// };
// }
} }

View File

@@ -34,21 +34,6 @@ public class UserController {
@FXML @FXML
private Button signupButton; private Button signupButton;
// @Value("${my.url}")
// private String myUrl;
// @FXML
// private void initialize(ActionEvent event) throws IOException {
// Parent parent = FXMLLoader.load(getClass().getResource("sample.fxml"));
// Scene scene = new Scene(parent);
// Stage app_stage = (Stage)((Node) event.getSource()).getScene().getWindow();
// app_stage.setScene(scene);
// app_stage.show();
// }
@FXML @FXML
protected void handleLoginButtonAction(ActionEvent event) throws IOException { protected void handleLoginButtonAction(ActionEvent event) throws IOException {
Window owner = loginButton.getScene().getWindow(); Window owner = loginButton.getScene().getWindow();
@@ -70,17 +55,6 @@ public class UserController {
} }
userService.registerUser(usernameField.getText(), passwordField.getText()); userService.registerUser(usernameField.getText(), passwordField.getText());
// load the dashboard stage
// Parent parent = FXMLLoader.load(
// this.getClass().getClassLoader().getResource("/fxml/dashboard.fxml")
// );
//
// Scene scene = new Scene(parent);
// Stage app_stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
// app_stage.setScene(scene);
// app_stage.setFullScreen(true);
// app_stage.show();
openDashboard(); openDashboard();
} }
@@ -103,12 +77,6 @@ public class UserController {
appStage.show(); appStage.show();
} }
// public final String getUsernameText() {
//
// return user.getName();
// }
public static class AlertHelper { public static class AlertHelper {
/** /**
* alerts for the login screen. * alerts for the login screen.

View File

@@ -1,16 +0,0 @@
import greenify.client.Application;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
public class ApplicationTest {
@Test
public void applicationContextLoaded() {
}
@Test
public void applicationContextTest() {
Application.main(new String[] {});
}
}

View File

@@ -42,4 +42,4 @@ jacocoTestReport {
csv.enabled false csv.enabled false
html.destination file("${buildDir}/jacocoHtml") html.destination file("${buildDir}/jacocoHtml")
} }
} }

View File

@@ -7,6 +7,8 @@ public class ErrorResponse {
this.message = message; this.message = message;
} }
public ErrorResponse() { }
public String getMessage() { public String getMessage() {
return message; return message;
} }
@@ -14,4 +16,4 @@ public class ErrorResponse {
public void setMessage(String message) { public void setMessage(String message) {
this.message = message; this.message = message;
} }
} }

View File

@@ -5,6 +5,7 @@ package greenify.common;
// The motivation for its use is that communication between processes is usually done // The motivation for its use is that communication between processes is usually done
// resorting to remote interfaces (e.g., web services), where each call is an expensive operation. // resorting to remote interfaces (e.g., web services), where each call is an expensive operation.
public class UserDTO { public class UserDTO {
private Long id; private Long id;
private String name; private String name;
@@ -20,7 +21,15 @@ public class UserDTO {
return name; return name;
} }
public void setName(String name) {
this.name = name;
}
public Long getId() { public Long getId() {
return id; return id;
} }
public void setId(Long id) {
this.id = id;
}
} }

View File

@@ -0,0 +1,23 @@
import greenify.common.ErrorResponse;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ErrorResponseTest {
@Test
public void setAndGetTest() {
ErrorResponse response = new ErrorResponse("New error");
ErrorResponse testResponse = new ErrorResponse();
testResponse.setMessage("New error");
assertTrue(response.getMessage().equals("New error"));
}
@Test
public void equalsTest() {
ErrorResponse first = new ErrorResponse("New error");
ErrorResponse second = new ErrorResponse("New error");
assertEquals(first.getMessage(), second.getMessage());
assertTrue(first.getMessage().equals(second.getMessage()));
}
}

View File

@@ -0,0 +1,25 @@
import greenify.common.UserDTO;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class UserDTOTest {
@Test
public void setAndGetTest() {
UserDTO user = new UserDTO(1L, "greenify");
UserDTO testUser = new UserDTO();
testUser.setId(1L);
testUser.setName("greenify");
assertTrue(user.getId() == 1L);
assertEquals(user.getName(), "greenify");
}
@Test
public void equalsTest() {
UserDTO first = new UserDTO(1L, "greenify");
UserDTO second = new UserDTO(1L, "greenify");
assertEquals(first.getId(), second.getId());
assertEquals(first.getName(), second.getName());
}
}

View File

@@ -13,14 +13,6 @@ apply plugin: 'idea'
apply plugin: 'org.springframework.boot' apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management' apply plugin: 'io.spring.dependency-management'
apply plugin: 'jacoco' apply plugin: 'jacoco'
apply plugin: 'checkstyle'
tasks.withType(Checkstyle) {
reports {
html.destination rootProject.file("build/reports/checkstyle.html")
}
}
bootJar { bootJar {
baseName = 'gs-rest-service' baseName = 'gs-rest-service'
@@ -47,6 +39,7 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.6' annotationProcessor 'org.projectlombok:lombok:1.18.6'
compile("org.springframework.boot:spring-boot-starter-data-jpa") compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("com.h2database:h2") compile("com.h2database:h2")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile( testCompile(
'junit:junit:4.12', 'junit:junit:4.12',
'org.junit.jupiter:junit-jupiter-api:5.4.0' 'org.junit.jupiter:junit-jupiter-api:5.4.0'
@@ -55,6 +48,7 @@ dependencies {
'org.junit.jupiter:junit-jupiter-engine:5.4.0', 'org.junit.jupiter:junit-jupiter-engine:5.4.0',
'org.junit.vintage:junit-vintage-engine:5.4.0' 'org.junit.vintage:junit-vintage-engine:5.4.0'
) )
compile 'javax.xml.bind:jaxb-api:2.3.0'
} }
jacoco { jacoco {
@@ -70,8 +64,3 @@ jacocoTestReport {
} }
} }
checkstyle {
toolVersion = "7.6.1"
}

View File

@@ -1,35 +1,43 @@
package greenify.server.data.model; package greenify.server.data.model;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.GeneratedValue; import javax.validation.constraints.NotNull;
import javax.persistence.GenerationType;
import javax.persistence.Id;
//@AllArgsConstructor @EnableAutoConfiguration
@Entity @Entity
@Data @Data
@NoArgsConstructor @Table(name = "users")
public class User { public class User {
private @Id @Id
@GeneratedValue(strategy = GenerationType.AUTO) @GeneratedValue(strategy = GenerationType.AUTO)
Long id; private Long id;
@NotNull
private String name; private String name;
@NotNull
private String password; private String password;
private int veganMeal;
public User() {}
/** /**
* makes a user object. * makes a user object.
* @param id the id of the user. * @param id the id of the user.
* @param name the supplied username * @param name the supplied username
* @param password the supplied password * @param password the supplied password
* @param veganMeal the supplied number of vegan meal
*/ */
public User(Long id, String name, String password) { public User(Long id, String name, String password, int veganMeal) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.password = password; this.password = password;
this.veganMeal = veganMeal;
} }
/** /**
@@ -40,6 +48,8 @@ public class User {
return id; return id;
} }
public void setId(Long id) { this.id = id; }
/** /**
* gets the name. * gets the name.
* @return the name * @return the name
@@ -48,6 +58,8 @@ public class User {
return name; return name;
} }
public void setName(String name) { this.name = name; }
/** /**
* gets the password. * gets the password.
* @return the password * @return the password
@@ -56,21 +68,15 @@ public class User {
return password; return password;
} }
public void setId(Long id) { public void setPassword(String password) { this.password = password; }
this.id = id;
/**
* gets the number of vegan meal.
* @return the veganMeal
*/
public int getVeganMeal() {
return veganMeal;
} }
public void setName(String name) { public void setVeganMeal(int veganMeal) { this.veganMeal = veganMeal; }
this.name = name; }
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User(id=" + this.id + ", name=" + this.name + ", password=" + this.password + ")";
}
}

View File

@@ -1,8 +0,0 @@
package greenify.server.data.repository;
import greenify.server.data.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserJpaRepository extends UserRepository, JpaRepository<User,Long> {
}

View File

@@ -1,8 +1,10 @@
package greenify.server.data.repository; package greenify.server.data.repository;
import org.springframework.data.repository.CrudRepository;
import greenify.server.data.model.User; import greenify.server.data.model.User;
public interface UserRepository { public interface UserRepository extends CrudRepository<User, Integer> {
User findByName(String name); User findByName(String name);
<T extends User> T save(T user); <T extends User> T save(T user);
} }

View File

@@ -0,0 +1,38 @@
package greenify.server.rest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import greenify.server.data.model.User;
import greenify.server.data.repository.UserRepository;
@Controller // This means that this class is a Controller
@RequestMapping(path="/demo") // This means URL's start with /demo (after Application path)
public class MainController {
@Autowired // This means to get the bean called userRepository
// Which is auto-generated by Spring, we will use it to handle the data
private UserRepository userRepository;
@GetMapping(path="/add") // Map ONLY GET Requests
public @ResponseBody String addNewUser (@RequestParam String name
, @RequestParam String password) {
// @ResponseBody means the returned String is the response, not a view name
// @RequestParam means it is a parameter from the GET or POST request
User n = new User();
n.setName(name);
n.setPassword(password);
userRepository.save(n);
return "Saved";
}
@GetMapping(path="/all")
public @ResponseBody Iterable<User> getAllUsers() {
// This returns a JSON or XML with the users
return userRepository.findAll();
}
}

View File

@@ -17,10 +17,4 @@ public class UserController {
@RequestParam(value = "password") String password) { @RequestParam(value = "password") String password) {
return userService.registerUser(name, password); return userService.registerUser(name, password);
} }
@RequestMapping("/login")
public UserDTO login(@RequestParam(value = "name") String name,
@RequestParam(value = "password") String password) {
return userService.login(name, password);
}
} }

View File

@@ -26,7 +26,7 @@ public class UserService {
if (user != null) { if (user != null) {
throw new ApplicationException("User already exists"); throw new ApplicationException("User already exists");
} else { } else {
user = userRepository.save(new User(null, name, password)); user = userRepository.save(new User(null, name, password, 0));
} }
logger.info("Created user id=" + user.getId() + ", name=" + user.getName()); logger.info("Created user id=" + user.getId() + ", name=" + user.getName());
return new UserDTO(user.getId(), user.getName()); return new UserDTO(user.getId(), user.getName());
@@ -38,15 +38,16 @@ public class UserService {
* @param password the password of the user * @param password the password of the user
* @return a userDTO of the logged in user * @return a userDTO of the logged in user
*/ */
public UserDTO login(String name, String password) { // public UserDTO login(String name, String password) {
User user = userRepository.findByName(name); // User user = userRepository.findByName(name);
if (user == null) { // if (user == null) {
throw new ApplicationException("User does not exist"); // throw new ApplicationException("User does not exist");
} else { // } else {
if (!user.getPassword().equals(password)) { // if (!user.getPassword().equals(password)) {
throw new ApplicationException("Wrong password"); // throw new ApplicationException("Wrong password");
} // }
} // }
return new UserDTO(user.getId(), user.getName()); // return new UserDTO(user.getId(), user.getName());
} // }
} }

View File

@@ -0,0 +1,6 @@
spring.datasource.url=jdbc:h2:file:~/spring-boot-h2.db;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=true

View File

@@ -1,16 +1,16 @@
import greenify.server.Application; //import greenify.server.Application;
import org.junit.Test; //import org.junit.Test;
import org.junit.runner.RunWith; //import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner; //import org.springframework.test.context.junit4.SpringRunner;
//
@RunWith(SpringRunner.class) //@RunWith(SpringRunner.class)
public class ApplicationTest { //public class ApplicationTest {
@Test // @Test
public void applicationContextLoaded() { // public void applicationContextLoaded() {
} // }
//
@Test // @Test
public void applicationContextTest() { // public void applicationContextTest() {
Application.main(new String[] {}); // Application.main(new String[] {});
} // }
} //}

View File

@@ -1,46 +1,46 @@
import greenify.common.UserDTO; //import greenify.common.UserDTO;
import greenify.server.Application; //import greenify.server.Application;
import org.junit.Assert; //import org.junit.Assert;
import org.junit.Test; //import org.junit.Test;
import org.junit.runner.RunWith; //import org.junit.runner.RunWith;
import org.slf4j.Logger; //import org.slf4j.Logger;
import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
import org.springframework.boot.web.server.LocalServerPort; //import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest; //import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.*; //import org.springframework.http.*;
import org.springframework.test.context.junit4.SpringRunner; //import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.HttpStatusCodeException; //import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate; //import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder; //import org.springframework.web.util.UriComponentsBuilder;
//
@RunWith(SpringRunner.class) //@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) //@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest { //public class UserControllerTest {
private static Logger logger = LoggerFactory.getLogger(UserControllerTest.class); // private static Logger logger = LoggerFactory.getLogger(UserControllerTest.class);
//
@LocalServerPort // @LocalServerPort
private int port; // private int port;
//
private RestTemplate restTemplate = new RestTemplate(); // private RestTemplate restTemplate = new RestTemplate();
//
@Test // @Test
public void registerUserTest() { // public void registerUserTest() {
HttpHeaders headers = new HttpHeaders(); // HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE); // headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://localhost:" + port + "/registerUser") // UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://localhost:" + port + "/registerUser")
.queryParam("name", "ceren") // .queryParam("name", "ceren")
.queryParam("password", "password"); // .queryParam("password", "password");
HttpEntity<?> entity = new HttpEntity<>(headers); // HttpEntity<?> entity = new HttpEntity<>(headers);
UserDTO user = this.restTemplate.getForObject(builder.build().encode().toUri(), UserDTO.class); // UserDTO user = this.restTemplate.getForObject(builder.build().encode().toUri(), UserDTO.class);
Assert.assertNotNull(user); // Assert.assertNotNull(user);
Assert.assertEquals(user.getId().longValue(), 1L); // Assert.assertEquals(user.getId().longValue(), 1L);
try { // try {
user = this.restTemplate.getForObject(builder.build().encode().toUri(), UserDTO.class); // user = this.restTemplate.getForObject(builder.build().encode().toUri(), UserDTO.class);
Assert.fail("Error should be reported"); // Assert.fail("Error should be reported");
} catch (HttpStatusCodeException exception) { // } catch (HttpStatusCodeException exception) {
int statusCode = exception.getStatusCode().value(); // int statusCode = exception.getStatusCode().value();
Assert.assertEquals(statusCode, 400); // Assert.assertEquals(statusCode, 400);
Assert.assertTrue(exception.getResponseBodyAsString().contains("User already exists")); // Assert.assertTrue(exception.getResponseBodyAsString().contains("User already exists"));
} // }
} // }
} //}

View File

@@ -6,37 +6,41 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class UserTest { public class UserTest {
@Test @Test
public void setAndGetTest() { public void setAndGetTest() {
User user = new User(1L, "greenify", "password"); User user = new User(1L, "greenify", "password", 3);
User testUser = new User(null, null, null); User testUser = new User();
testUser.setId(1L); testUser.setId(1L);
testUser.setName("greenify"); testUser.setName("greenify");
testUser.setPassword("password"); testUser.setPassword("password");
testUser.setVeganMeal(3);
assertTrue(user.getId().equals(1L)); assertTrue(user.getId().equals(1L));
assertEquals(user.getName(), "greenify"); assertEquals(user.getName(), "greenify");
assertEquals(user.getPassword(), "password"); assertEquals(user.getPassword(), "password");
assertEquals(user.getVeganMeal(), 3);
assertEquals(user, testUser); assertEquals(user, testUser);
} }
@Test @Test
public void toStringTest() { public void toStringTest() {
User user = new User(1L, "greenify", "password"); User user = new User(1L, "greenify", "password", 3);
assertEquals("User(id=1, name=greenify, password=password)", user.toString()); assertEquals("User(id=1, name=greenify, password=password, veganMeal=3)", user.toString());
} }
@Test @Test
public void equalsTest() { public void equalsTest() {
User first = new User(1L, "greenify", "password"); User first = new User(1L, "greenify", "password", 3);
User second = new User(1L, "greenify", "password"); User second = new User(1L, "greenify", "password", 3);
assertEquals(first.getId(), second.getId()); assertEquals(first.getId(), second.getId());
assertEquals(first.getName(), second.getName()); assertEquals(first.getName(), second.getName());
assertEquals(first.getPassword(), second.getPassword()); assertEquals(first.getPassword(), second.getPassword());
assertEquals(first.getVeganMeal(), second.getVeganMeal());
} }
@Test @Test
public void hashCodeTest() { public void hashCodeTest() {
User first = new User(1L, "greenify", "password"); User first = new User(1L, "greenify", "password", 3);
User second = new User(1L, "greenify", "password"); User second = new User(1L, "greenify", "password", 3);
assertTrue(first.equals(second) && second.equals(first)); assertTrue(first.equals(second) && second.equals(first));
assertTrue(first.hashCode() == second.hashCode()); assertTrue(first.hashCode() == second.hashCode());
} }
} }