Mockito doReturn always return NULL - java

I have a class that I wish to test using Mockito. The problem I am facing is that when the Mock is called it always returns a null value.
I can see when I debug that Mockito see the mock but always returns null. My understanding is that in the CUT that when the client.sendMessage is called it will return the value for Transaction that I have created in the #Test.
Any suggestions on what I am doing wrong?
The class under test:
public String SendMessage(String ID, String body) {
String receipt = null;
Map<String, Integer> Transaction = null;
try {
Transaction = client.sendMessage(ID, body);
} catch(Exception e) {
receipt = "FAIL";
return receipt;
}
receipt = Transaction.get("receipt").toString();
return receipt;
}
My test method is:
#Mock
private MessageSenderClient client;
#InjectMocks
MessageSender ms;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testPushNotificationProcessorTransactionID() {
String Id = "1234";
String body = "Test Message";
Map<String, Integer> Transaction = new HashMap<String, Integer>();
Transaction.put("Id", 123456);
client = Mockito.mock(PushNotificationClient.class);
Mockito.doReturn(Transaction).when(client).sendMessage(Matchers.anyString(), Matchers.anyString());
String transactionID = ms.SendPushMessage(Id, body);
assertEquals(transactionID, "1");
}

Related

Spring boot unit test by Junit 5 why mock return null

Here is my controller:-
#RestController
#RequestMapping(ScoreBoardController.REQUEST_URL)
public class ScoreBoardController {
public static final String REQUEST_URL = "/score";
public static final String POST_REQUEST = "/add";
public static final String GET_ALL_REQUEST = "/all";
public static final String DELETE_BY_ID = "/deleteById/{id}";
public static final String DELETE_BY_NAME = "/deleteByName/{name}";
public static final String DELETE_BY_ROUND_PATH_VAR = "/deleteByRoundPath/{round}";
public static final String DELETE_BY_ROUND_PARAM = "/deleteByRoundParam";
public static final String UPDAATE_NAME_BY_ID_PATH_VAR = "/updateNameByIdPath/{id}/{name}";
public static final String UPDATE_NAME_BY_ID_PARAM = "/updateNameByIdParam";
public static final String UPDATE_RESULT_BY_ID_PATH_VAR = "/updateResultByIdPath/{id}/{result}";
public static final String UPDATE_RESULT_BY_ID_PARAM = "/updateResultByIdParam";
public static final String GET_BY_ID = "/getById/{id}";
private ScoreService scoreService;
public ScoreBoardController(ScoreService scoreBoardService) {
this.scoreService = scoreBoardService;
}
#ApiOperation(value = "Add a new score post socre as json body")
#PostMapping(path = POST_REQUEST, produces = MediaType.APPLICATION_JSON_VALUE)
public Score save(
#ApiParam(value = "A score to save into db")
#RequestBody Score score) {
return scoreService.save(score);
}
}
Service:-
#Service
public class ScoreService {
#Autowired
private ScoreRepository scoreRepository;
public Score save(Score score) {
return scoreRepository.save(score);
}
}
It works if I POST request by the postman
http://localhost:8080/score/add
{
"name": "test4",
"round": 4,
"result": "WIN"
}
It saves the data in DB and response same score.
But I am trying to unit test as follows that doesn't work as expected.
#WebMvcTest({ScoreBoardController.class})
class ScoreBoardControllerTest {
#MockBean
private ScoreService scoreService;
#Autowired
private MockMvc mockMvc;
#Test
void save() throws Exception {
Score expectedScore = new Score(1l, "name", 1, Result.WIN, null);
String jsonScore = "{ \"id\": 1, \"name\": \"name\", \"round\" : 1, \"result\" : \"WIN\", \"timestamp\": null }";
when(scoreService.save(expectedScore)).thenReturn(expectedScore);
var ret = scoreService.save(expectedScore); // mock return correctly
mockMvc.perform( post(ScoreBoardController.REQUEST_URL+ScoreBoardController.POST_REQUEST)
.content(jsonScore)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1l))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("name"))
.andExpect(MockMvcResultMatchers.jsonPath("$.result").value("WIN"));
}
}
On the above test when I perform post request scoreService.save(score) return null instead of mocked score in the controller code. Why? What is wrong?
The mock returning null means that the values passed to save() is not equal to the expected value. This is what I would try:
Is Score implementing equals() correctly?
Try with when(scoreService.save(any())).thenReturn(expectedScore). This should always return expectedScore regardless of the parameter.
Try to debug it and check what the passed Score actually looks like.

NullPointerException when using #Inject Annotation in JavaEE

I have the following service class:
#Singleton
public class QuotesLoaderBean {
Properties quotes;
Properties names;
#Inject
public QuoteRepository repo;
public QuotesLoaderBean() {
}
#PostConstruct
public void init() {
InputStream quotesInput = this.getClass().getClassLoader().getResourceAsStream("quotes.properties");
InputStream namesInput = this.getClass().getClassLoader().getResourceAsStream("names.properties");
quotes = new Properties();
names = new Properties();
try {
quotes.load(quotesInput);
names.load(namesInput);
} catch (IOException ex) {
Logger.getLogger(QuotesLoaderBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
public Citation createCitation(String quote) {
Citation citation = new Citation();
citation.setQuote(quote);
citation.setWho(getName());
repo.save();
return citation;
}
public Citation getCitation() {
Citation citation = new Citation();
citation.setQuote(getQuote());
citation.setWho(getName());
return citation;
}
public String getQuote() {
Enumeration keys = quotes.propertyNames();
int elementNumber = new Random().nextInt(quotes.keySet().size());
return quotes.getProperty(getElement(keys, elementNumber));
}
public String getName() {
Enumeration keys = names.propertyNames();
int elementNumber = new Random().nextInt(names.keySet().size());
return names.getProperty(getElement(keys, elementNumber));
}
private String getElement(Enumeration keys, int elementNumber) {
int i = 0;
while (keys.hasMoreElements()) {
if (i == elementNumber) {
return (String) keys.nextElement();
} else {
i++;
keys.nextElement();
}
}
return null;
}
}
The Repository class is very simple for test purposes:
#Singleton
public class QuoteRepository {
public String save() {
Gson gson = new GsonBuilder().create();
return "Saved...";
}
}
When I test the createCitation method I always get a NullPointerException but I cant figure out why. Something is not working with Injection. I also have a api class that is annotated with #Stateless and there I can easily inject the service class with with the #Inject annotation.
When I test the createCitation method I always get a NullPointerException
You can't simply test your application, because you delegated the responsibility of objects creation to the container which in unit tests (I assume you use it) does not exist.
public Citation createCitation(String quote) {
Citation citation = new Citation();
citation.setQuote(quote);
citation.setWho(getName());
repo.save(); // repo isn't initialized
return citation;
}
If you want to test your code, mock repo object or use integration test.

Mockito showing 0 interactions with mock

Here is my code:
public class S3Dao {
private final AmazonS3Client amazonS3Client;
static final String BUCKET_NAME = "myBucket";
public S3Dao(final AmazonS3Client amazonS3Client) {
this.amazonS3Client = amazonS3Client;
}
public void put(ModelObject modelObject, String playlistId) {
this.amazonS3Client.putObject(BUCKET_NAME, playlistId, new Gson().toJson(modelObject));
}
}
And my test code:
#ExtendWith(MockitoExtension.class)
public class S3DaoTest {
private S3Dao s3Dao;
#Mock
private AmazonS3Client s3Client;
#BeforeEach
public void beforeEach() {
this.s3Dao = new S3Dao(this.s3Client);
}
#Test
public void putTest() {
ModelObject obj = new ModelObject("name", new ArrayList<>());
String json = new Gson().toJson(obj);
verify(s3Client).putObject(S3Dao.BUCKET_NAME, "playlistId", json);
this.s3Dao.put(obj, "playlistId");
}
}
The resulting error is
Wanted but not invoked:
s3Client.putObject(
"myBucket",
"playlistId",
"{"name":"name","children":[]}"
);
-> at com.amazon.amazon.live.destination.playlist.dao.S3DaoTest.putTest(S3DaoTest.java:34)
Actually, there were zero interactions with this mock.
Indeed, removing the verify causes the test to pass without issue. Why isn't this working?
Move the verify after the method call
#Test
public void putTest() {
ModelObject obj = new ModelObject("name", new ArrayList<>());
String json = new Gson().toJson(obj);
this.s3Dao.put(obj, "playlistId");
verify(s3Client).putObject(S3Dao.BUCKET_NAME, "playlistId", json);
}

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ArrayList cannot be returned by getDetails()

here is code
public class TodoBusinessImpl {
BusinessManager businessManager;
public TodoBusinessImpl(BusinessManager businessManager) {
this.businessManager = businessManager;
}
public List<String> retrieveTodosRelatedToSpring(String user) {
List<String> filteredTodos = new ArrayList<String>();
Map<String, String> test = businessManager.getDetails();
return filteredTodos;
}
}
what is wrong with that? what i am doing wrong
public class MockitoTest {
private BusinessManager businessManager;
#Before
public void setUp() {
businessManager = Mockito.mock(BusinessManager.class);
}
#Test
public void retrieveTodosRelatedToSpringTest() {
TodoBusinessImpl todoBusinessImpl = new TodoBusinessImpl(businessManager);
Mockito.when(todoBusinessImpl.retrieveTodosRelatedToSpring("test"))
.thenReturn(Arrays.asList("test"));
}
}
This is the test class. Getting exception that org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ArrayList cannot be returned by getDetails()
You have to call the method that you're testing not mock it's behavior "not tell it what to do when it's called".
Instead of:
Mockito.when(todoBusinessImpl.retrieveTodosRelatedToSpring("test")).thenReturn(Arrays.asList("test"));
You should do this:
List<String> list = todoBusinessImpl.retrieveTodosRelatedToSpring("test");
// print list or assert it's content to make sure you're getting the right response

mockito stubbing returns null

I am using mockito as mocking framework. I have a scenerio here, my when(abc.method()).thenReturn(value) does not return value, instead it returns null.
Here is how my class and test looks like.
public class foo(){
public boolean method(String userName) throws Exception {
ClassA request = new ClassA();
request.setAbc(userName);
ClassB response = new ClassB();
try {
response = stub.callingmethod(request);
} catch (Exception e) {
}
boolean returnVal = response.isXXX();
return returnVal;
}
Now follwoing is the test
#Test
public void testmethod() throws Exception{
//arrange
String userName = "UserName";
ClassA request = new ClassA();
ClassB response = new ClassB();
response.setXXX(true);
when(stub.callingmethod(request)).thenReturn(response);
//act
boolean result = fooinstance.lockLogin(userName);
//assert
assertTrue(result);
}
stub is mocked using mockito i.e using #Mock. The test throws NullPointerException in class foo near boolean retrunVal = response.isXXX();
the argument matcher for stub.callingmethod(request).thenReturn(response) is comparing for reference equality. You want a more loose matcher, like this I think:
stub.callingmethod(isA(ClassA.class)).thenReturn(response);
Ensure that your ClassA implements its own equals and that it is correctly implemented.

Categories

Resources