Trying mock void method using JUnit4 then getting below exception
Below is the class definition
#Mock
private TestService service;
#Mock
private DatabaseService mockDatabase;
#Before
public void setUpMock() throws Exception {
LOGGER.info("########### Moke setUp started ###########");
conn = Mockito.mock(Connection.class);
MockitoAnnotations.initMocks(this);
LOGGER.info("########### Moke setUp completed ###########");
}
#Test
public void testSuccess() {
try {
when(mockDatabase.getDBConnection()).thenReturn(conn);
Mockito.doNothing().when(service).deleteKeyInfo(mockDatabase.getDBConnection(), userBn, 1, "1");
} catch (Exception e) {
fail("### testDeviceIdNull ### Failed with following error: " + getStackTrace(e));
}
}
But getting below exception
java.lang.AssertionError: ### Failed with following error: org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed
Below is the void method
public void deleteKeyInfo(Connection conn, UserBn userBn, Integer smId, String dId) throws Exception {
// Deleting key
}
You're nesting mocking inside of mocking. You're calling getDBConnection(), which does some mocking, before you've finished the mocking for service.
Mockito doesn't like it when you do this.
Replace:
try {
when(mockDatabase.getDBConnection()).thenReturn(conn);
Mockito.doNothing().when(service).deleteKeyInfo(mockDatabase.getDBConnection(), userBn, 1, "1");
}
with:
try {
when(mockDatabase.getDBConnection()).thenReturn(conn);
some_variable_name = mockDatabase.getDBConnection();
Mockito.doNothing().when(service).deleteKeyInfo(some_variable_name, userBn, 1, "1");
}
Please check this : Unfinished Stubbing Detected in Mockito for more information
Related
I am trying to get some context of the result of the test run in the #AfterTest. I would like to have, at bare minimum, knowledge if it passed or not and ideally also the thrown exception if there is one.
However, every parameter I try seems to not be resolvable and I can't find any documentation on what should be available.
Code:
public class TestClass {
#AfterEach
public void afterEach(
TestInfo testInfo, //works, but no report on state of test
// none of these work
TestExecutionSummary summary,
TestExecutionResult result,
TestFailure fail,
Optional<Throwable> execOp,
Throwable exception
) {
// ...
}
}
What can I do to get this context?
Not sure if this is what you want, but you can use either a TestExecutionListener or a TestWatcher (there are also other ways that you can check in documentation).
An example of TestWatcher can be found here: TestWatcher in junit5 and a more detailed explanation here: https://www.baeldung.com/junit-testwatcher.
The following code example was partially taken from here.
public class TestResultLoggerExtension implements TestWatcher, AfterAllCallback {
...
#Override
public void testSuccessful(ExtensionContext context) {
System.out.println("Test Successful for test {}: ", context.getDisplayName();
}
#Override
public void testFailed(ExtensionContext context, Throwable cause) {
System.out.println("Test Failed for test {}, with cause {}", context.getDisplayName(), cause.getMessage());
}
}
You test class would be something like this:
#ExtendWith(TestResultLoggerExtension.class)
public class TestClass {
You can adapt the logic to your needs.
More References:
https://junit.org/junit5/docs/current/user-guide/#extensions-test-result-processing
https://junit.org/junit5/docs/current/user-guide/#launcher-api-listeners-custom
I am using Springboot with Mockito for test.
I want mock a function that she return a string.
Code impl:
EDIT
public String replaceContent(String url, String replace, String value) {
return url.replace(replace, value);
}
public ResponseEntity<List<MonitorOperativeFront>> getOperativesMonitor(String userCode) {
log.info(" ---> LogInfo: start ");
String url = this.replaceContent(this.urlBase,this.stringReplace,userCode);
log.info(" ---> LogInfo: call to: " + url);
List<MonitorOperativeFront> list= null ;
MonitorOperative[] operative = this.restTemplate.getForObject(url, MonitorOperative[].class);
list.add(new MonitorOperativeFront(operative[0].getId()));
log.info(" ---> LogInfo: Success ");
return new ResponseEntity<>(list, HttpStatus.OK);
}
Code Test:
#Mock
Mockito mk;
#InjectMocks
MonitorServiceImpl monitorService;
#Test
public void testG() throws Exception {
String url = "prueba/test";
this.mk.when( monitorService.replaceContent("prueba/{id}", "{id}", "test"))
.thenReturn(url);
ResponseEntity<List<MonitorOperativeFront>> operative2 = monitorService.getOperativesMonitor("n11111");
assertEquals(true,true);
Err:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
I checked that my function return success "prueba/test" but in mockito I get a error and I don't know resolve...
The #Mock should be the class which has the Method you would like to mock. If you would like to mock the replaceContent you have to write
#Mock
MonitorServiceImpl monitorServiceMock;
#InjectMocks
SomeUserOfMonitorServiceImpl monitorServiceImplUser;
#Test
public void testG() throws Exception {
String url="http://dsgdfgdf/"
Mockito.when( monitorServiceMock.replaceContent("prueba/{id}", "{id}", "test"))
.thenReturn(url));
//Do Something which calls the monitorService.replaceContent
monitorServiceImplUser.doSomething();
I'm having issues with SonarQube raising issues with several of my unit tests, prompting the following issue:
#InjectMocks
private MessageEscaper escaper;
#Mock
private SLogger mockLogger;
#Mock
private Messagetext mocktext;
#Before
public void setup() throws Exception {
escaper = new MessageEscaper ();
MockitoAnnotations.initMocks(this);
}
#Test
public void Message() {
assertTrue(escaper.handleText(mockText));
verify(mockLogger).logMessage(mockText);
assertEquals(true, escaper.handleText(mockText));
}
The escaper.handleText(mockText) returns a Boolean. Even if i have assert statements i still get an issue " Add at least one assertion to this test case". Though both the assert statements are similar i felt sonar might pick at least one of them.
this is the method that gets the actual call.
public boolean handleText(MessageText text)
{
try {
Message message = context.getMessage();
String serviceName = Util.getServiceName(message);
text.put(MESSAGE_OPERATION, serviceName);
} catch (CustomException | RuntimeException e) {
if (LOG.isLoggable(Level.ERROR)) {
LOG.warning("Unable to store : " + UtilLog.print(e));
}
}
return true;
}
Any help would be appreciated.
Try updating the plugin version.Worked for me
I was facing the same problem, I was able solve it with the following code...
#Test(expected = Test.None.class /* no exception expected */)
rather than
#Test()
Im trying to make a simple as a can example which could be found on official PowerMock's page (here).I' doing a partial mock of this class :
public class Simple {
public String doMe() {
return privateMethod();
}
private String privateMethod() {
return "POWERMOCK sucks";
}
}
And wrote a simple test class :
#RunWith(PowerMockRunner.class)
#PrepareForTest(Simple.class)
public class ProcessorTest {
#Test
public void doMe() throws Exception {
Simple spy = PowerMockito.spy(new Simple());
PowerMockito.doReturn("hello").when(spy, "privateMethod");
String res = spy.doMe();
PowerMockito.verifyPrivate(spy, Mockito.times(1000)).invoke(
"privateMethod");
Assert.assertEquals( res, "hello");
}
}
But result is like this :
java.lang.AssertionError: expected [hello] but found [null]
Expected :hello
Actual :null
<Click to see difference>
at org.testng.Assert.fail(Assert.java:94)
So Powermock not only fails to mock the privateMethod and return 'null' it's OK with that it was called 1000 times when it was not.
It get even more creepy if I try to mess with mocking like this :
PowerMockito.doReturn(1).when(spy, "privateMethod");
So I'm trying to return an Integer instead of String from the privateMethod.
Then I get this :
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Integer cannot be returned by doMe()
doMe() should return String
***
So by some reason Powermock is trying to mock public doMe method.
Any one understands what is happining? I dont.
Thanks.
My environment is :
Java 1.8, Mockito 1.10.19, Powermock 1.6.2
Ok, I found solution, the problem was that JUnit's #RunWith did not actually do the trick so I had to extend from PowerMockTestCase to make it work. The test looks like this now and it works like a charm:
#PrepareForTest(Simple.class)
public class ProcessorTest extends PowerMockTestCase {
#Test
public void doMe() throws Exception {
Simple spy = PowerMockito.spy(new Simple());
PowerMockito.doReturn("hello").when(spy, "privateMethod");
String res = spy.doMe();
PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke(
"privateMethod");
Assert.assertEquals( res, "hello");
}
}
I want the closeSession() method to throw an Exception when it is called so that I can test to see my logging is being done. I have mocked the Crypto object as mockCrypto and set it up as follows:
#Test
public void testdecrpyMcpDataExceptions() throws Exception {
Crypto mockCrypto = Mockito.mock(Crypto.class);
try {
mockCrypto = CryptoManager.getCrypto();
logger.info("Cyrpto Initialized");
} finally {
logger.info("Finally");
try {
logger.info("About to close Crypto!");
Mockito.doThrow(new CryptoException("")).when(mockCrypto).closeSession();
mockCrypto.closeSession();
} catch (CryptoException e) {
logger.warn("CryptoException occurred when closing crypto session at decryptMcpData() in CipherUtil : esi");
}
}
}
However when I run it I get the error :
Argument passed to when() is not a mock!
Am I mocking the class wrong or am I just missing something?
don't you overwrite your mock at
mockCrypto = CryptoManager.getCrypto();
Tested
#Test(expected=RuntimeException.class)
public void testdecrpyMcpDataExceptions() throws Exception {
Crypto mockCrypto = mock(Crypto.class);
doThrow(new RuntimeException()).when(mockCrypto).closeSession();
mockCrypto.closeSession();
}
works fine.
this line is overwriting your mock:
mockCrypto = CryptoManager.getCrypto();
and thats why it fails.