I am using Java unit tests. When we give the parameters correctly, the unit test should work without any errors (green). But I am getting such an error. Java version 1.8
Expecting code to raise a throwable.
TicTacToeService
public class TicTacToeService {
public void play(int x, int y) {
if(x<0)
throw new IllegalArgumentException("x cannot be negative");
if (y < 0)
throw new IllegalArgumentException("y cannot be negative");
if (x > 2)
throw new IllegalArgumentException("x cannot be greater than 2");
if (y > 2)
throw new IllegalArgumentException("y cannot be greater than 2");
}
}
TicTacToeTest
public class TicTacToeTest {
private TicTacToeService ticTacToeService = new TicTacToeService();
#Test
public void givenXIsNegativeExpectException(){
int x = -1;
int y = 1;
Assertions.assertThatThrownBy(() -> ticTacToeService.play(x, y))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("X cannot be negative");
}
#Test
public void givenYIsNegativeExpectException(){
int x = 1;
int y = -1;
Assertions.assertThatThrownBy(() -> ticTacToeService.play(x, y))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("y cannot be negative");
}
}
dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation("org.modelmapper:modelmapper:2.3.7")
implementation 'org.springframework.boot:spring-boot-starter-validation'
testCompile group: 'junit', name: 'junit', version: '4.4'
implementation 'org.liquibase:liquibase-core'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testCompile group: 'org.assertj', name: 'assertj-core', version: '3.6.1'
testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.7.0'
}
What is the problem? please help me
I suspect that you are using assertThatThrownBy but in reality, you want to use assertThrows. You can check this link for example.
I can declare my own custom runtime exception write it as below
service class
#Service
public class TicTacToeService {
public void play(int x, int y) {
if (x < 0)
throw new XNegativeException("x cannot be negative");
if (y < 0)
throw new YNegativeException("y cannot be negative");
if (x > 2)
throw new XLimitException("x cannot be greater than 2");
if (y > 2)
throw new YLimitException("y cannot be greater than 2");
}
static class XNegativeException extends RuntimeException{
public XNegativeException(String message) {
super(message);
}
}
static class YNegativeException extends RuntimeException{
public YNegativeException(String message) {
super(message);
}
}
static class XLimitException extends RuntimeException{
public XLimitException(String message) {
super(message);
}
}
static class YLimitException extends RuntimeException{
public YLimitException(String message) {
super(message);
}
}
}
Test File
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TicTacToeServiceTest {
private final TicTacToeService ticTacToeService = new TicTacToeService();
#Test
void testXIsNegative() {
Assertions.assertThrows(TicTacToeService.XNegativeException.class,
() -> ticTacToeService.play(-1, 0));
}
#Test
void testYIsNegative() {
Assertions.assertThrows(TicTacToeService.YNegativeException.class,
() -> ticTacToeService.play(0, -898));
}
#Test
void testXLimitReached() {
Assertions.assertThrows(TicTacToeService.XLimitException.class,
() -> ticTacToeService.play(3, 0));
}
#Test
void testYLimitReached() {
Assertions.assertThrows(TicTacToeService.YLimitException.class,
() -> ticTacToeService.play(0, 3));
}
}
Related
in my spring boot application I'm using main arguments to pass variables and need to call a method to save an object into database based on some code in main class.
I'm using main class like that:
#SpringBootApplication
public class MainClass {
#Autowired
private RecordingService recordingService;
public MainClass(String arg1, String arg2) {
this.setArg1(arg1);
this.setArg2(arg2);
}
public static void main(String args[]) {
String ip = null;
String op = null;
if (args != null & args.length > 0) {
for (int i = 0; i < args.length; i++) {
if (args[i].equalsIgnoreCase("-ip")) {
ip = args[i + 1].trim();
} else if (args[i].equalsIgnoreCase("-op")) {
op = args[i + 1].trim();
}
i++;
}
}
if (ip == null || op == null) {
System.out.println("Invalid input or output path.");
} else {
MainClass reader = new MainClass(ip, op);
Recording recording = new Recording();
.
.
some code...
.
.
this.recordingService.insertIntoDB(recording);
}
}
}
}
And this is service class:
#Service
public class RecordingService {
#Autowired
private RecordingRepository recordingRepository;
public RecordingService() {
}
public void insertToDatabase(Recording recording) {
try {
Recording recording = new Recording();
this.recordingRepository.save(recording);
} catch (Exception e) {
e.printStackTrace();
}
}
}
When I run this code I get NullPointerException, What is the mistake in this code?
You are starting the main method without Spring so Spring won't create RecordingService. It can be changed using CommandLineRunner:
#SpringBootApplication
public class MainClass implements CommandLineRunner {
#Autowired
private RecordingService recordingService;
public static void main(String[] args) {
SpringApplication.run(MainClass.class, args);
}
#Override
public void run(String... args) {
//your main code here
}
}
I am new to Pact contract testing
Gradle dependencies
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//pact
testImplementation 'au.com.dius.pact.consumer:junit5:4.3.6'
}
Rest Controller
#RestController
public class CodeController {
#GetMapping("/hello")
public String hello() {
return "Hello from spring with pact project";
}
}
ControllerClient
#Component
public class ControllerClient{
private final RestTemplate restTemplate;
public ControllerClient(#Value("${user-service.base-url}") String baseUrl) {
this.restTemplate = new RestTemplateBuilder().rootUri(baseUrl).build();
}
public String getHello() {
return restTemplate.getForObject("/hello", String.class);
}
}
ConsumerContractTest
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = "user-service.base-url:http://localhost:8080", classes = ControllerClient.class)
#ExtendWith(PactConsumerTestExt.class)
public class ConsumerContractTest {
#Autowired
private ControllerClient controllerClient;
#Pact(consumer = "code-consumer")
public RequestResponsePact pactForHelloWorld(PactDslWithProvider builder) {
return builder
.given("hello world")
.uponReceiving("hello request")
.path("/hello")
.method(HttpMethod.GET.name())
.willRespondWith().status(200)
.body(new PactDslJsonBody().stringType("Hello from spring with pact project"))
.toPact();
}
#PactTestFor(pactMethod = "pactForHelloWorld", pactVersion = PactSpecVersion.V3)
#Test
public void userExists() {
String returnStr = controllerClient.getHello();
assertThat(returnStr).isEqualTo("Hello from spring with pact project");
}
}
When I execute this consumer contract test I get below exception
au.com.dius.pact.consumer.PactMismatchesException: The following requests were not received:
method: GET
path: /hello
query: {}
headers: {}
matchers: MatchingRules(rules={})
generators: Generators(categories={})
body: MISSING
at au.com.dius.pact.consumer.junit.JUnitTestSupport.validateMockServerResult(JUnitTestSupport.kt:110)
at au.com.dius.pact.consumer.junit5.PactConsumerTestExt.afterTestExecution(PactConsumerTestExt.kt:468)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterTestExecutionCallbacks$9(TestMethodTestDescriptor.java:233)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:273)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$14(TestMethodTestDescriptor.java:273)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
....
The issue is that your test doesn't send the request to the Pact mock service - that's why you're getting the error "The following requests were not received".
You should modify your unit test as follows:
#PactTestFor(pactMethod = "pactForHelloWorld", pactVersion = PactSpecVersion.V3)
#Test
public void userExists(MockServer mockServer) {
// TODO: set endpoint on controllerClient to mockServer.getUrl()
String returnStr = controllerClient.getHello();
assertThat(returnStr).isEqualTo("Hello from spring with pact project");
}
See an example of this approach here.
I am having trouble getting mapstruct and immutables to work.
#Value.Immutable
public abstract class FoobarValue {
public abstract Integer foo();
}
#Value.Immutable
public abstract class TargetFoo {
public abstract Integer foo();
}
#Mapper
public interface ImmutableMapper {
ImmutableMapper INSTANCE = Mappers.getMapper(ImmutableMapper.class);
public TargetFoo toTarget(FoobarValue foobarValue);
}
Main class to test
public class FoobarValueMain {
public static void main(String... args) {
FoobarValue value = ImmutableFoobarValue.builder()
.foo(2)
.build();
ImmutableMapper mapper = ImmutableMapper.INSTANCE;
System.out.println(mapper.toTarget(value).foo());
}
}
The error that I get is
Exception in thread "main" java.lang.IllegalStateException: Cannot build TargetFoo, some of required attributes are not set [foo]
at org.play.ImmutableTargetFoo$Builder.build(ImmutableTargetFoo.java:158)
at org.play.ImmutableMapperImpl.toTarget(ImmutableMapperImpl.java:21)
at org.play.FoobarValueMain.main(FoobarValueMain.java:12)
My build.gradle is as follows
ext {
mapstructVersion = "1.4.0.Beta2"
immutablesVersion = "2.8.2"
}
dependencies {
annotationProcessor "org.immutables:value:$immutablesVersion" // <--- this is important
annotationProcessor "org.mapstruct:mapstruct-processor:1.4.0.Beta2"
compileOnly "org.immutables:value:$immutablesVersion"
implementation "org.mapstruct:mapstruct:${mapstructVersion}"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
As per reference this should all work out of the box. What am I missing here ?
The reason why it doesn't work is because you are not using the JavaBean convention.
You need to prefix your methods with get
e.g.
#Value.Immutable
public abstract class TargetFoo {
public abstract Integer getFoo();
}
I'm attempting to create basic Axon/Spring application by tutorial, but faced with strange error like: NoHandlerForCommandException: No handler was subscribed to command. It seems that Axon can't see #CommandHandler annotation.
Here my files:
aggregate
#Aggregate
#NoArgsConstructor
public class Account {
#AggregateIdentifier
private UUID accountId;
private Double balance;
#CommandHandler
public Account(CreateAccountCommand command) {
apply(new AccountCreatedEvent(command.getAccountId(), command.getName()));
}
#EventSourcingHandler
protected void on(AccountCreatedEvent event) {
this.accountId = event.getAccountId();
this.balance = 0.0;
}
}
event
#AllArgsConstructor
#Getter
public class AccountCreatedEvent {
private UUID accountId;
private String name;
}
command
#Getter
public class CreateAccountCommand {
#TargetAggregateIdentifier
private UUID accountId;
private String name;
public CreateAccountCommand(UUID accountId, String name) {
this.accountId = accountId;
this.name = name;
}
}
spring boot conf
#SpringBootApplication
public class App {
#Configuration
public static class TestConfiguration {
#Bean
public EventStorageEngine inMemoryEventStorageEngine() {
return new InMemoryEventStorageEngine();
}
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
this is how i send cmd
#Component
public class AppLoader {
#Autowired
private CommandGateway cmdGateway;
#PostConstruct
public void init() {
cmdGateway.send(new CreateAccountCommand(UUID.randomUUID(), "test"));
}
}
my build.gradle
buildscript {
ext {
springBootVersion = '2.0.5.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'io.yourpoint.nettnews'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'org.axonframework', name: 'axon-test', version: '3.3.5'
compile group: 'org.axonframework', name: 'axon-spring-boot-starter', version: '3.3.5'
compile('org.springframework.boot:spring-boot-starter-webflux')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('io.projectreactor:reactor-test')
}
It is very likely that performing the CommandGateway#send() call in a #PostConstruct is to early for Axon..
As it currently stands, all the command, event and query handlers typically get registered after all your beans have been initialized.
Moving the CommandGateway#send() behind a REST endpoint should give you a big enough time frame to ensure all the handlers have been registered.
So in short, it's a timing issues why you get the NoHandlerForCommandException.
We (at AxonIQ) see benefit in sending some sort of application events as soon as all the handlers have been registered. That's a thing for the future though.
Hope this helps you out #Benjamin!
I am in the process of developing a Spring Boot application and came across this error when starting the server. I am not sure if I am incorrectly defining any annotations or missing any dependencies. Any help would be appreciated.
Main class:
#SpringBootApplication
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class DemoApplication {
public static void main(String[] args) {
System.out.println("Hello world");
SpringApplication.run(DemoApplication.class, args);
}
}
UserService class:
#Service
public class UserService implements IUserService {
#Autowired
private UserDAO userDAO;
#Override
public List<UserDTO> getAllUsers() {
List<User> entities = userDAO.getUsers();
List<UserDTO> users = new ArrayList<UserDTO>();//Will never use directly User Object, will be using Tranferable objects
Iterator<User> iterator = entities.iterator();
while(iterator.hasNext()) {
User user = iterator.next();
users.add(ApiDTOBuilder.userToUserDTO(user));//We are building UserDTO object.
}
return users;
}
#Override
public UserDTO getUserByUsername(String username) {
User user = userDAO.getUser(username);
return ApiDTOBuilder.userToUserDTO(user);
}
#Override
public void createUser(UserDTO user) {
userDAO.createUser(ApiDTOBuilder.userDTOToUser(user));
}
#Override
public void updateUser(UserDTO user) {
userDAO.updateUser(ApiDTOBuilder.userDTOToUser(user));
}
#Override
public void deleteUser(String username) {
userDAO.deleteUser(username);
}
}
UserDAO class:
#Repository
public class UserDAO implements IUserDAO {
#PersistenceContext
EntityManager em;//JPA EntityManager is used to access a database in a particular application. It is used to manage persistent entity instances, to find entities by their primary key identity(As here is Username), and to query over all entities.
#Override
#Transactional
public User getUser(String username) {
return em.find(User.class, username); //Here entitymanager can find the username as it has the capability to find an entity by unique identifies
}
#Override
#Transactional
public List<User> getUsers() {
List<User> resultList = em.createQuery("FROM user_tbl", User.class).getResultList();
return resultList;
}
#Override
#Transactional
public void createUser(User user) {
em.persist(user);//Make an instance managed and persistent.
}
#Override
#Transactional
public void updateUser(User user) {
em.merge(user);//Merge the state of the given entity into the current persistence context.
}
#Override
#Transactional
public void deleteUser(String username) {
User user = this.getUser(username);
em.remove(user);//Remove the entity instance.
}
}
Build.gradle:
buildscript {
ext {
springBootVersion = '2.0.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final')
compile('javax.xml.bind:jaxb-api:2.2.11')
compile('org.springframework.boot:spring-boot-starter-test:2.0.2.RELEASE')
compile('com.sun.xml.bind:jaxb-core:2.2.11')
compile('com.sun.xml.bind:jaxb-impl:2.2.11')
runtime('org.springframework.boot:spring-boot-devtools')
runtime('mysql:mysql-connector-java')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
Error message:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userDAO in com.example.demo.service.UserService required a bean of type 'javax.persistence.EntityManagerFactory' that could not be found.
Action:
Consider defining a bean of type 'javax.persistence.EntityManagerFactory' in your configuration.
I saw all the relevant answers and tried to implement those suggestions like adding dependencies, adding notations in the main class, etc. But it shows the same error. Please someone help me out. Thank you in advance.
P.S: Github link of my application: https://github.com/heliOpenxCell/demo
i got the same your problem, just add this to your maven or gradle, it work for me!
Maven:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>9.0.10</version>
</dependency>
Gradle:
compile group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '9.0.10'