For the following classes Texts ...
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Collections;
import java.util.List;
import hrisey.Parcelable;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
#Parcelable
public final class Texts implements android.os.Parcelable {
#NonNull List<Text> texts = Collections.emptyList();
public boolean hasTexts() {
return !texts.isEmpty() && textsHaveValues();
}
private boolean textsHaveValues() {
for (Text text : texts) {
if (TextUtils.isEmpty(text.getValue())) {
return false;
}
}
return true;
}
}
... and Text ...
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import hrisey.Parcelable;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
#Parcelable
public final class Text implements android.os.Parcelable {
private String textKey;
private String value;
}
... I wrote this unit test:
#RunWith(JUnit4.class)
public class TextsTest {
private Texts texts;
#Before
public void setUp() {
texts = new Texts();
}
#Test
public void hasTextsWithSingleEmptyItem() throws Exception {
texts.setTexts(Collections.singletonList(new Text()));
assertThat(texts.hasTexts()).isFalse();
}
}
The test succeeds in Android Studio 2.1.3 but it fails when I run ./gradlew clean test on my machine (MacOS 10.11.6, El Capitain, Java 1.7.0_79). Here is the error output:
com.example.model.TextsTest > hasTextsWithSingleEmptyItem FAILED
org.junit.ComparisonFailure: expected:<[fals]e> but was:<[tru]e>
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(
NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(
DelegatingConstructorAccessorImpl.java:45)
at com.example.model.TextsTest.hasTextsWithSingleEmptyItem(TextsTest.java:31)
Related posts
creating instance of object using reflection , when the constructor takes an array of strings as argument
IllegalArgumentException with constructing class using reflection and array arguments
How do you mock TextUtils? The part TextUtils.isEmpty(text.getValue()) should always be false when using the default Android test stubs.
Be sure to use a suitable implementation or consider using a different set of string utilities you already might have available with some other dependencies.
Edit by JJD
You are right, thanks! I use the Unmock plugin. So I had to unmock the relevant package to expose TextUtils in the unit tests:
unMock {
keepStartingWith "android.text."
}
Related
I am a student trying to learn about apache kafka.
I am trying to send a JSON object as a message using kafka in spring boot using java.
But as I try to send it,it throws an error saying that my model class cannot be cast to a string even though i have mentioned the Json serializer in application.properties file.
The exception is:
java.lang.ClassCastException: class com.example.demo.model.BookES cannot be cast to class java.lang.String (com.example.demo.model.BookES is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')
My application.properties file is
server.port=8081
spring.kafka.consumer.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.producer.bootstrap-servers=localhost:9092
spring.kafka.producer.key-serializer=org.apache.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
My controller class where i am trying to send my message
#PostMapping("/publish")
public ResponseEntity<String> publish(#RequestBody BookES bookES){
logger.info("in publish method");
kafkaProducer.sendMessage(bookES);
return ResponseEntity.ok("Json message sent to kafka topic");
}
My Kafka producer class which has the sendMessage method:
package com.example.demo.kafka;
import org.apache.kafka.clients.admin.NewTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import com.example.demo.controller.BookController;
import com.example.demo.model.Book;
import com.example.demo.model.BookES;
#Service
public class KafkaProducer {
#Autowired
private NewTopic topic;
Logger logger = LoggerFactory.getLogger(KafkaProducer.class);
private String topicName = "bookmanagement";
#Autowired
private KafkaTemplate<String, BookES> kafkaTemplate;
public void sendMessage(BookES bookES) {
logger.info("in sendMessage method");
logger.info(String.format("Message sent -> %s",bookES.toString()));
Message<BookES> message = MessageBuilder.withPayload(bookES).setHeader(KafkaHeaders.TOPIC, topic.name()).build();
kafkaTemplate.send(message);
}
}
My model class:
package com.example.demo.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
#Document(indexName="my-application")
#Data
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
public class BookES{
#Override
public String toString() {
return "BookES [bookId=" + bookId + ", bookName=" + bookName + ", description=" + description + "]";
}
#Id
private String bookId;
private String bookName;
private String description;
public String getBookId() {
// TODO Auto-generated method stub
return this.bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void setBookId(String bookId) {
this.bookId = bookId;
}
}
my project is on the github link: github link
I tried anotating my model class with with different annotations like #JsonSerializer,etc.. but with no success.
The response i got on postman on trying to post is:
{
"timestamp": "2022-11-22T11:24:30.738+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "Can't convert value of class com.example.demo.model.BookES to class org.apache.kafka.common.serialization.StringSerializer specified in value.serializer",
"path": "/books/publish"
}
You need to provide your own serializer that can serialize your BookES into byte array. Here is a class I use as generic Json serializer. It should handle your class just fine:
package ***;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.mgnt.utils.JsonUtils;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Serializer;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
#Component
public class GenericJsonSerializer implements Serializer<Object> {
#Override
public byte[] serialize(String s, Object obj) {
byte[] result;
try {
result = JsonUtils.writeObjectToJsonString(obj).getBytes(StandardCharsets.UTF_8);
} catch (JsonProcessingException e) {
throw new SerializationException("Error occurred while serializing " + obj.getClass().getCanonicalName() + " to byte[]", e);
}
return result;
}
}
In your properties you will need to register this class as your deserializer. Note that when you read your message back, if you want it to be read as BookES class you will need to provide deserializer class that would take byte array and convert it back into class BookES. (You will have to implement org.apache.kafka.common.serialization.Deserializer interface). In my example I used class JsonUtils that comes from Open Source Java library MgntUtils (written and maintained by me). You can easily replace it and just use ObjectMapper class from Json-Jackson library or use GSON library. But It might make it simpler to use JsonUtils. If you wish to use it here is the Javadoc for JsonUtils class. The MgntUtils library could be obtained as Maven Artifact or on The Github
I'm trying to write unit test for my method called getBestSellers().
Here it is:
package bookstore.scraper.book.scrapingtypeservice;
import bookstore.scraper.enums.Bookstore;
import bookstore.scraper.book.Book;
import bookstore.scraper.fetcher.empik.EmpikFetchingBookService;
import bookstore.scraper.fetcher.merlin.MerlinFetchingBookService;
import bookstore.scraper.urlproperties.EmpikUrlProperties;
import bookstore.scraper.urlproperties.MerlinUrlProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import static bookstore.scraper.utilities.JSoupConnector.connect;
#Service
public class BestSellersService {
private final EmpikUrlProperties empikUrlProperties;
private final MerlinUrlProperties merlinUrlProperties;
private final EmpikFetchingBookService empikBookService;
private final MerlinFetchingBookService merlinBookService;
#Autowired
public BestSellersService(EmpikFetchingBookService empikBookService, MerlinFetchingBookService merlinBookService, EmpikUrlProperties empikUrlProperties, MerlinUrlProperties merlinUrlProperties) {
this.empikBookService = empikBookService;
this.merlinBookService = merlinBookService;
this.empikUrlProperties = empikUrlProperties;
this.merlinUrlProperties = merlinUrlProperties;
}
public Map<Bookstore, List<Book>> getBestSellers() {
Map<Bookstore, List<Book>> bookstoreWithBestSellers = new EnumMap<>(Bookstore.class);
bookstoreWithBestSellers.put(Bookstore.EMPIK, empikBookService
.get5BestSellersEmpik(connect(empikUrlProperties.getEmpik().getBestSellers())));
bookstoreWithBestSellers.put(Bookstore.MERLIN, merlinBookService
.get5BestSellersMerlin(connect(merlinUrlProperties.getMerlin().getBestSellers())));
return bookstoreWithBestSellers;
}
}
So, first I prepared test which looks like this:
package bookstore.scraper.book.scrapingtypeservice;
import bookstore.scraper.book.Book;
import bookstore.scraper.dataprovider.EmpikBookProvider;
import bookstore.scraper.dataprovider.MerlinBookProvider;
import bookstore.scraper.enums.Bookstore;
import bookstore.scraper.fetcher.empik.EmpikFetchingBookService;
import bookstore.scraper.fetcher.merlin.MerlinFetchingBookService;
import bookstore.scraper.urlproperties.EmpikUrlProperties;
import bookstore.scraper.urlproperties.MerlinUrlProperties;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
public class BestSellersServiceTest {
#Mock
private EmpikFetchingBookService empikBookService;
#Mock
private MerlinFetchingBookService merlinBookService;
#Mock
private EmpikUrlProperties empikUrlProperties;
#Mock
private MerlinUrlProperties merlinUrlProperties;
#InjectMocks
private BestSellersService bestSellersService;
#Test
public void getBestSellers() {
List<Book> merlinBestsellers = EmpikBookProvider.prepare5Bestsellers();
List<Book> empikBestsellers = MerlinBookProvider.prepare5Bestsellers();
when(empikBookService.get5BestSellersEmpik(any())).thenReturn(empikBestsellers);
when(merlinBookService.get5BestSellersMerlin(any())).thenReturn(merlinBestsellers);
//when(empikUrlProperties.getEmpik().getBestSellers()).thenReturn(anyString());
//when(merlinUrlProperties.getMerlin().getBestSellers()).thenReturn(anyString());
Map<Bookstore, List<Book>> actualMap = bestSellersService.getBestSellers();
Map<Bookstore, List<Book>> expectedMap = null;
assertEquals(expectedMap, actualMap);
assertThat(actualMap).hasSize(expectedMap.size());
}
}
Without setting behaviour for properties classes as I thought it is unnecessary, because I put any() when calling empikBookService.get5BestSellersEmpik (same for merlinBookService) but it threw NPE when calling
bookstoreWithBestSellers.put(Bookstore.EMPIK, empikBookService
.get5BestSellersEmpik(connect(empikUrlProperties.getEmpik().getBestSellers())));
I've debugged it and I have seen that
empikUrlProperties.getEmpik().getBestSellers()))
was given me NPE.
So I set behaviour like this:
when(empikUrlProperties.getEmpik().getBestSellers()).thenReturn(anyString());
when(merlinUrlProperties.getMerlin().getBestSellers()).thenReturn(anyString());
and now it is giving me here NPE with stactrace:
ava.lang.NullPointerException
at bookstore.scraper.book.scrapingtypeservice.BestSellersServiceTest.getBestSellers(BestSellersServiceTest.java:48)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
.
.
.
connect method used in tested method:
#UtilityClass
public class JSoupConnector {
public static Document connect(String url) {
try {
return Jsoup.connect(url).get();
} catch (IOException e) {
throw new IllegalArgumentException("Cannot connect to" + url);
}
}
}
Properties class (same for merlin)
package bookstore.scraper.urlproperties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
#Getter
#Setter
#Component
#ConfigurationProperties("external.library.url")
public class EmpikUrlProperties {
private Empik empik = new Empik();
#Getter
#Setter
public static class Empik {
private String mostPreciseBook;
private String bestSellers;
private String concreteBook;
private String romances;
private String biographies;
private String crime;
private String guides;
private String fantasy;
}
}
What am I making wrong? Why it didnt work in the first place when I put any()
There are many problems, but the main one is that you're misunderstanding how mocking, argument evaluation and any() work.
You're using
when(empikBookService.get5BestSellersEmpik(any())).thenReturn(empikBestsellers);
This tells the mock empikBookService than whenever its get5BestSellersEmpik method is called, it should return empikBestsellers, whetever the argument passed to the method is.
What does your actual code pass as argument when executing your test? It passes the value returned by
connect(empikUrlProperties.getEmpik().getBestSellers())
The key part is that this expression is evaluated first, and then its result is passed as argument to the get5BestSellersEmpik() method.
Just like when you do
System.out.println(a + b)
a + b is first evaluated. If the result is 42, then the value 42 is passed to println(), and println prints 42.
So, in order for your test not to fail, the expression
connect(empikUrlProperties.getEmpik().getBestSellers())
must be evaluated successfully. Its result doesn't matter, since you've configure your mock to accept any argument. But that's irrelevant.
You're trying to do
when(empikUrlProperties.getEmpik().getBestSellers()).thenReturn(anyString());
That doesn't make any sense.
First, because empikUrlProperties.getEmpik() will return null, since empikUrlProperties is a mock, and mocks return null by default. And null.getBestSellers() will thus cause a NullPointerException.
Second, because telling a mock that it should return any string doesn't make sense. If you don't care about the string it should return, then choose a string by yourself, and make it return that. anyString() actually returns null, so you're telling it to return null.
So you need to fix that. Always think about what your code is doing instead of trying to apply a recipe.
And finally, your test also calls connect(...), which is a staic method, that you haven't (and can't) mock. This method will be called too. And it tries to connect to an actual URL. So if nothing is responding during your test at that URL, that won't work either. This connect() method should really be part of a dependency of your service, and this dependency should be mocked.
When you set your mock :
when(empikUrlProperties.getEmpik().getBestSellers()).thenReturn(anyString());
You have mocked empikUrlProperties, which is great, BUT you have not told that mock what to do when getEmpik() is called on it. Consequently, that method call will return null both here in the test, and also (before you had this line) in the production code - so this is the cause of your NPE when getBestSellers() is called.
Consequently, set that mock up, something like :
#Mock
private EmpikUrlProperties empikUrlProperties;
#Mock
private EmpikUrlProperties.Empik empikMock;
when(empikUrlProperties.getEmpik()).thenReturn(empikMock);
when(empikMock.getBestSellers()).thenReturn(anyString());
I am using Micronaut as framework for developing an AWS Java Lambda.
Micronaut supports #Value for reading, well, "values".
#io.micronaut.context.annotation.Factory
public class SomeFactory {
public SomeFactory(
#io.micronaut.context.annotation.Value("${NameOfValue}")
final String value) {
...
}
...
}
When testing, I want to set "NameOfValue" to a specific value, how can I do that?
#io.micronaut.test.annotation.MicronautTest
class SomeLambdaIT {
#org.junit.jupiter.api.Test
void aTest() {
// When this test runs, "NameOfValue" shall be set to a specific value
}
}
When testing, I want to set "NameOfValue" to a specific value, how can
I do that?
You have a number of options.
One option is to define src/test/resources/application-test.yml and define the config setting there. That file will only be loaded in the test environment and any settings defined in that file will supersede values defined in src/main/resources/application.yml.
Another option that might make sense if you only want the special setting in play for this particular test is you can do something like this...
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
#MicronautTest(propertySources = "classpath:some-special-test-props.properties")
public class SomeTest {
#Test
void someTest() {
// ...
}
}
Then define src/test/resources/some-special-test-props.properties and assign the value there.
Yet another option is to mark your test with #Property:
import io.micronaut.context.annotation.Property;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
#MicronautTest
#Property(name="some.config.value", value = "My Test Value")
public class SomeTest {
#Test
void someTest() {
// ...
}
}
I hope that helps.
EDIT
A comment below includes "I did give it a try, but the #Property solution nor the some-special-test-props.properties works in my case.". I have created a sample app demonstrating each of these techniques. See the project at https://github.com/jeffbrown/markusschultevalue.
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/main/java/markusschultevalue/SomeWidget.java
package markusschultevalue;
public class SomeWidget {
private final String name;
public SomeWidget(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
https://github.com/jeffbrown/markusschultevalue/blob/master/src/main/java/markusschultevalue/SomeFactory.java
package markusschultevalue;
import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Value;
#Factory
public class SomeFactory {
private final String name;
// there are better ways to do this but
// this is consistent with the code in the
// question being asked...
public SomeFactory(#Value("${some.config.value}") String name) {
this.name = name;
}
#Bean
public SomeWidget createWidget() {
return new SomeWidget(name);
}
}
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/java/markusschultevalue/PropertyAnnotationTest.java
package markusschultevalue;
import io.micronaut.context.annotation.Property;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertEquals;
#MicronautTest
#Property(name="some.config.value", value="Some Widget Name")
public class PropertyAnnotationTest {
#Inject
SomeWidget someWidget;
#Test
void testWidget() {
assertEquals("Some Widget Name", someWidget.getName());
}
}
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/java/markusschultevalue/ConfigFileTest.java
package markusschultevalue;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertEquals;
// This will load the config value
// from src/test/resources/some-widget-test-config.yml
#MicronautTest(propertySources = "classpath:some-widget-test-config.yml")
public class ConfigFileTest {
#Inject
SomeWidget someWidget;
#Test
void testWidget() {
assertEquals("Some Other Widget Name", someWidget.getName());
}
}
https://github.com/jeffbrown/markusschultevalue/blob/8131e96492356180e2c7fade09603bd41f8c8829/src/test/resources/some-widget-test-config.yml
some:
config:
value: Some Other Widget Name
Note that in your example you are referencing a config variable with "${NameOfValue}". If that is actually the name of your config variable, note that in code you need to reference that in valid kebab-case which would be "${name-of-value}".
I hope that helps.
I wanted to write unit test for my addTask method with mockito.
Here is the class that contains this method.
package controller;
import model.Task;
import model.User;
import repository.TaskActions;
import repository.UserActions;
import java.sql.SQLException;
import java.util.List;
public class ToDoEngine {
private TaskActions taskActions;
private UserActions userActions;
private User connectedUser;
public ToDoEngine(UserActions userStorage, TaskActions taskStorage) {
this.taskActions = taskStorage;
this.userActions = userStorage;
}
public boolean signIn(String username, String password) throws SQLException {
connectedUser = new User(username, password);
if (!userActions.signIn(connectedUser)) {
return false;
}
connectedUser.setID(retrieveConnectedUserID(connectedUser));
return true;
}
private int retrieveConnectedUserID(User connectedUser) throws SQLException {
return userActions.retrieveUserID(connectedUser);
}
public void addTask(String taskName) throws SQLException {
taskActions.addTask(new Task(taskName), connectedUser);
}
}
Here are my attempts. Unfortunately, I've got error. Below, I am gonna present you stacktrace:
package controller;
import model.Task;
import model.User;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import repository.TaskActions;
import repository.UserActions;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ToDoEngineTest {
#Mock
TaskActions taskActionsMock;
#Mock
UserActions userActionsMock;
private ToDoEngine toDoEngine;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
toDoEngine = new ToDoEngine(userActionsMock, taskActionsMock);
}
#Test
public void addTask() throws SQLException {
Task taskName = new Task("wash");
User user = new User("admin","123");
toDoEngine.addTask("wash");
verify(taskActionsMock).addTask(taskName,user);
}
}
stacktrace:
Argument(s) are different! Wanted:
taskActionsMock.addTask(
Task(taskName=wash),
model.User#1b71f500
);
-> at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
Actual invocation has different arguments:
taskActionsMock.addTask(
Task(taskName=wash),
null
);
-> at controller.ToDoEngine.addTask(ToDoEngine.java:40)
Comparison Failure: <Click to see difference>
Argument(s) are different! Wanted:
taskActionsMock.addTask(
Task(taskName=wash),
model.User#1b71f500
);
-> at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
Actual invocation has different arguments:
taskActionsMock.addTask(
Task(taskName=wash),
null
);
-> at controller.ToDoEngine.addTask(ToDoEngine.java:40)
at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
User and Task class contains hashCode and Equals method.
Task
package model;
import lombok.*;
#Getter
#Setter
#AllArgsConstructor
#ToString
#NoArgsConstructor
#EqualsAndHashCode
public class Task {
private String taskName;
}
User:
package model;
import lombok.*;
#RequiredArgsConstructor
#Getter
#Setter
#EqualsAndHashCode
public class User {
private final String name;
private final String password;
private int ID;
}
Thanks in advance for help. :D
In your test case you are attempting to verify a call onto this method:
public void addTask(String taskName) throws SQLException {
taskActions.addTask(new Task(taskName), connectedUser);
}
With this:
User user = new User("admin","123");
...
verify(taskActionsMock).addTask(taskName,user);
The failure message ...
Actual invocation has different arguments:
taskActionsMock.addTask(
Task(taskName=wash),
null
);
... tells us that the value of connectedUser in the test call is null.
Looking at your code the connectedUser member of ToDoEngine is populated by a call to the signIn() method but your test case is not invoking that method and hence connectedUser is null when addTask is invoked by your test.
So, if you don't need/want to test that the correct user is supplied to addTask then just change your verify call to: verify(taskActionsMock).addTask(taskName,null)
However, that feels like a sidestep so instead you should ensure that connectedUser is not null and is the value you supplied to the verify call in your test case.
Your verify method specifies that you expect addTask to be called with specific taskName and user objects.
verify(taskActionsMock).addTask(taskName,user);
But since your connected user is null this expectation fails.
If you do not care about the connected user you can use matchers to tell Mockito to ignore its actual value. E.G.
verify(taskActionsMock).addTask(ArgumentMatchers.eq(taskName), ArgumentMatchers.any());
Or if you do care about the user just setup your ToDoEngine to have connected user.
I'm trying to walk through this guide:
http://www.playframework.com/documentation/2.2.x/JavaGuide2 , but it lacks some explanations which make me lost. More preciesly:
a)at the end of "Starting with the User class" paragraph, I should have got error. I didn't. I thought "whatever" and moved along, which, in retrospect might have been a mistake.
b) I progressed to the "first test" , but it did not write where am I supposed to put my test. So, I put it in ApplicationTest.java. It failed my tests however, saying ebean was not defined. So, after googling a bit I tried to add ebean.default="models.*" in application.conf. It worked, but now I have
[error] Test ApplicationTest.createAndRetrieveUser failed:
javax.persistence.PersistenceException:
java.sql.SQLException: Attempting to obtain a connection from a pool
that has already been shutdown.
I don't understand what's wrong.
my application test
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.JsonNode;
import models.User;
import org.junit.*;
import play.mvc.*;
import play.test.*;
import play.data.DynamicForm;
import play.data.validation.ValidationError;
import play.data.validation.Constraints.RequiredValidator;
import play.i18n.Lang;
import play.libs.F;
import play.libs.F.*;
import static play.test.Helpers.*;
import static org.fest.assertions.Assertions.*;
import static org.junit.Assert.*;
import play.libs.*;
import com.avaje.ebean.Ebean;
public class ApplicationTest {
#Test
public void simpleCheck() {
int a = 1 + 1;
assertThat(a).isEqualTo(2);
}
#Test
public void renderTemplate() {
Content html = views.html.index.render("Your new application is ready.");
assertThat(contentType(html)).isEqualTo("text/html");
assertThat(contentAsString(html)).contains("Your new application is ready.");
}
#Test
public void createAndRetrieveUser() {
new User("bob#gmail.com", "Bob", "secret").save();
User bob = User.find.where().eq("email", "bob#gmail.com").findUnique();
assertNotNull(bob);
assertEquals("Bob", bob.name);
}
}
User class
package models;
import javax.persistence.*;
import play.db.ebean.*;
import com.avaje.ebean.*;
#Entity
public class User extends Model {
#Id
public String email;
public String name;
public String password;
public User(String email, String name, String password) {
this.email = email;
this.name = name;
this.password = password;
}
public static Finder<String,User> find = new Finder<String,User>(
String.class, User.class
);
}
application.conf
#tried with 'db.*' uncommented as well as with commented
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.default.user=sa
db.default.password=""
db.default.jndiName=DefaultDS
# end of 'db.*'
ebean.default="models.*"
# Root logger:
logger.root=ERROR
# Logger used by the framework:
logger.play=INFO
# Logger provided to your application:
logger.application=DEBUG
The test createAndRetrieveUser() according to the tutorial should be in test/models/ModelsTest.java. You put it in ApplicationTest.java.