This is my code:
public void analyze(String url) throws SiteBusinessException {
Document doc = null;
Response response = null;
try {
response = Jsoup.connect(url).execute();
doc = Jsoup.connect(url).get();
} catch (IOException e) {
LOGGER.warn("Cannot analyze site [url={}, statusCode={}, statusMessage={} ]", new Object[] {url, response.statusCode(), response.statusMessage()});
throw new SiteBusinessException(response.statusMessage(), String.valueOf(response.statusCode()));
}
}
How can I test this method using PowerMock? I want to write test to check that when invoke .execute() then throw IOException and it catch then throw SiteBusinessException.
My code of test.
#RunWith(PowerMockRunner.class)
#PrepareForTest({Jsoup.class})
Test(expected = SiteBusinessException.class)
public void shouldThrowIOException() throws Exception {
Connection connection = PowerMockito.mock(Connection.class);
Response response = PowerMockito.mock(Response.class);
PowerMockito.when(connection.execute()).thenReturn(response);
PowerMockito.mockStatic(Jsoup.class);
expect(Jsoup.connect(SITE_URL)).andReturn(connection);
replay(Jsoup.class);
PowerMockito.when(Jsoup.connect(SITE_URL).execute()).thenThrow(new IOException());
AnalyzerService sut = new AnalyzerServiceImpl();
sut.analyzeSite(SITE_URL);
}
I got
java.lang.Exception: Unexpected exception, expected<com.siteraport.exception.SiteBusinessException> but was<java.lang.IllegalStateException>
??
You need to create a static mock of the Jsoup class. Once you have created such a mock in your test case, you can code your expectations using it.
Please see mock static method using PowerMockito documentation.
Here the Testcase using Mockito and PowerMockito:
I was able to mock the execute method using Mockito + Powermockito (you are using both EasyMock and Mockito?) The code in the test case looks as below:
#RunWith(PowerMockRunner.class)
#PrepareForTest({Jsoup.class})
public class MyClassTest {
#Test(expected = SiteBusinessException.class)
public void shouldThrowIOException() throws Exception {
String SITE_URL = "some_url_string";
Connection connection = Mockito.mock(Connection.class);
Mockito.when(connection.execute()).thenThrow(new IOException("test"));
PowerMockito.mockStatic(Jsoup.class);
PowerMockito.when(Jsoup.connect(Mockito.anyString())).
thenReturn(connection);
AnalyzerService sut = new AnalyzerService();
sut.analyze(SITE_URL);
}
}
Related
I need to test some REST client. For that purpose I'm using org.mockserver.integration.ClientAndServer
I start my server. Create some expectation. After that I mock my client. Run this client. But when server receives request I see in logs:
14:00:13.511 [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - received binary request:
505249202a20485454502f322e300d0a0d0a534d0d0a0d0a00000604000000000000040100000000000408000000000000ff0001
14:00:13.511 [MockServer-EventLog0] INFO org.mockserver.log.MockServerEventLog - unknown message format
505249202a20485454502f322e300d0a0d0a534d0d0a0d0a00000604000000000000040100000000000408000000000000ff0001
This is my test:
#RunWith(PowerMockRunner.class)
#PrepareForTest({NrfClient.class, SnefProperties.class})
#PowerMockIgnore({"javax.net.ssl.*"})
#TestPropertySource(locations = "classpath:test.properties")
public class NrfConnectionTest {
private String finalPath;
private UUID uuid = UUID.fromString("8d92d4ac-be0e-4016-8b2c-eff2607798e4");
private ClientAndServer mockServer;
#Before
public void startMockServer() {
mockServer = startClientAndServer(8888);
}
#After
public void stopServer() {
mockServer.stop();
}
#Test
public void NrfRegisterTest() throws Exception {
//create some expectation
new MockServerClient("127.0.0.1", 8888)
.when(HttpRequest.request()
.withMethod("PUT")
.withPath("/nnrf-nfm/v1/nf-instances/8d92d4ac-be0e-4016-8b2c-eff2607798e4"))
.respond(HttpResponse.response().withStatusCode(201));
//long preparations and mocking the NrfClient (client that actually make request)
//NrfClient is singleton, so had to mock a lot of methods.
PropertiesConfiguration config = new PropertiesConfiguration();
config.setAutoSave(false);
File file = new File("test.properties");
if (!file.exists()) {
String absolutePath = file.getAbsolutePath();
finalPath = absolutePath.substring(0, absolutePath.length() - "test.properties".length()) + "src\\test\\resources\\test.properties";
file = new File(finalPath);
}
try {
config.load(file);
config.setFile(file);
} catch(ConfigurationException e) {
LogUtils.warn(NrfConnectionTest.class, "Failed to load properties from file " + "classpath:test.properties", e);
}
SnefProperties spyProperties = PowerMockito.spy(SnefProperties.getInstance());
PowerMockito.doReturn(finalPath).when(spyProperties, "getPropertiesFilePath");
PowerMockito.doReturn(config).when(spyProperties, "getProperties");
PowerMockito.doReturn(config).when(spyProperties, "getLastUpdatedProperties");
NrfConfig nrfConfig = getNrfConfig();
NrfClient nrfClient = PowerMockito.spy(NrfClient.getInstance());
SnefAddressInfo snefAddressInfo = new SnefAddressInfo("127.0.0.1", "8080");
PowerMockito.doReturn(nrfConfig).when(nrfClient, "loadConfiguration", snefAddressInfo);
PowerMockito.doReturn(uuid).when(nrfClient, "getUuid");
Whitebox.setInternalState(SnefProperties.class, "instance", spyProperties);
nrfClient.initialize(snefAddressInfo);
//here the client makes request
nrfClient.run();
}
private NrfConfig getNrfConfig() {
NrfConfig nrfConfig = new NrfConfig();
nrfConfig.setNrfDirectConnection(true);
nrfConfig.setNrfAddress("127.0.0.1:8888");
nrfConfig.setSnefNrfService(State.ENABLED);
nrfConfig.setSmpIp("127.0.0.1");
nrfConfig.setSmpPort("8080");
return nrfConfig;
}
}
Looks like I miss some server configuration, or use it in wrong way.
Or, maybe the reason is in powermock: could it be that mockserver is incompatible with powermock or PowerMockRunner?
For below method i am writing JUnit testcase for sonarqube coverage.
#Transformer
public Object errorUnWrapper(Message<?> message) {
String value = "";
try {
if (!errorFlag) {
value = errorTransform(ESBConstants.SYSTEMERRCODE, ESBConstants.SYSTEMERROR, ESBConstants.SYSTEMTEXT);
} else {
value = getbankholiday.getErrorMessage();
}
} catch (Exception e) {
getbankholiday.getE2EObject().logMessage("3005", "Error Occurred in error unwrapper");
value = ESBConstants.SYSTEMERRORXML;
}
MessageHeaders headers = ((MessagingException) message.getPayload()).getFailedMessage().getHeaders();
return MessageBuilder.withPayload(value).copyHeaders(message.getHeaders())
.copyHeadersIfAbsent(headers).setHeader(ESBConstants.CONTENTTYPE, ESBConstants.CONTENTVALUE)
.build();
}
JUnit testcase:
#Test
void testErrorUnWrapper() throws IOException {
String xml = FileUtils.readFileToString(new File("src/test/resources/JunitTestCases/input/TC02_wltRequest.xml"),
"UTF-8");
test = MessageBuilder.withPayload(xml).build();
errorTransform.errorUnWrapper(test);
Assertions.assertTrue(true);
}
but, unable to mock or test the below line in JUnit testcase.
MessageHeaders headers = ((MessagingException) message.getPayload()).getFailedMessage().getHeaders();
Exception:
java.lang.ClassCastException: java.lang.String cannot be cast to org.springframework.messaging.MessagingException
at com.bt.or.esb.exceptions.ErrorTransform.errorUnWrapper(ErrorTransform.java:75)
at com.bt.or.esb.exceptions.ErrorTransformTest.testErrorUnWrapper(ErrorTransformTest.java:87)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Your productive code
(MessagingException) message.getPayload()
means you expect message.payload to be a MessagingException. But in your test, you create
MessageBuilder.withPayload(xml).build()
so payload will be a string. You need to build a message with a MessagingException as payload.
This usually means you need to refactor.
except for value everything else is common in if else and catch blocks
why don't you compute value first and then execute below two lines?
MessageHeaders headers = ((MessagingException) message.getPayload()).getFailedMessage().getHeaders();
return MessageBuilder.withPayload(value).copyHeaders(message.getHeaders()).copyHeadersIfAbsent(headers)
.setHeader(ESBConstants.CONTENTTYPE, ESBConstants.CONTENTVALUE).build();
I am trying to do a unit test for the code below. I am able to test the exception block but unable to test the below block as I am getting an exception.
How can I mock or set values to the ListTopicsResult topics = client.listTopics(), so that the flow goes into the if block?
if(!topics.names.get().isEmpty()) { response = true; }
public boolean isBrokerRunning() {
boolean response = false;
Properties property = new Properties();
try(AdminClient client = KafkaAdminClient.create(property)) {
ListTopicsResult topics = client.listTopics();
if(!topics.names.get().isEmpty()) {
response = true;
}
} catch(Exception ex) {
response = false;
}
}
KafkaAdminClient.create
This is a static function call, so you need to mock static function, You can use powermockit on top of mockito to mock static functions.
see this example
use mockito-inline can do this. need some trick
#Test
public void mockCreateAdmin() {
AdminClient mock = mock(KafkaAdminClient.class);
try (MockedStatic<Admin> staticMock = mockStatic(Admin.class)) {
staticMock.when(() -> Admin.create(any(Properties.class))).thenReturn(mock);
KafkaAdminClient adminClient = (KafkaAdminClient) KafkaAdminClient.create(new Properties());
// when
// then
assertEquals(mock, adminClient);
}
}
From below piece of code I am not able to mock checkAccountStatus and its coming as null. What changes do I need to do to resolve this issue?
Class
public AccessIDSearchResponse searchAccessID(AccessIDSearchRequest accessIDRequest) {
String[] productTypes = accessIDRequest.getProductTypes();
AccountResponse actResponse = checkAccountStatus(accessIDRequest);
System.out.println("Response is---->"+JsonService.getJsonFromObject(actResponse));
if (accessIDRequest.getSearchtype().equalsIgnoreCase("accountId") && !Utility.isEmpty(actResponse)
&& !"FREEVIEW".equalsIgnoreCase(actResponse.getAccountStatus())) {
errorHandler.error(ErrorMessages.EPO_EXISTINGTV_ERR_07, ErrorMessages.ACCESS_ID_NOT_FOUND);
}
}
public AccountResponse checkAccountStatus(AccessIDSearchRequest request) {
AccessIDSearchResponse response = new AccessIDSearchResponse();
SearchAccessIdContent content = new SearchAccessIdContent();
DTVNAccountDetails accountDetails = new DTVNAccountDetails();
accountDetails.setAccountNumber(request.getSearchvalue());
List<DTVNAccountDetails> list = new ArrayList<>();
list.add(accountDetails);
content.setDtvAccountList(list);
response.setContent(content);
return helper.getAccountStatus(response);
}
Helper
public AccountResponse getAccountStatus(AccessIDSearchResponse accessIDResponse) {
AccountResponse accountResponse = null;
AccountRequest request = new AccountRequest();
Account account = new Account();
account.setCustomerID(accessIDResponse.getContent().getDtvAccountList().get(0).getAccountNumber());
request.setAccount(account);
String response = dtvnClients.callandGetDtvnStatus(request);
System.out.println("Response is--->"+response);
if (!Utility.isEmpty(response)) {
accountResponse = JqUtil.runJqQueryAndGetString(".content.accountResponse", response,
AccountResponse.class);
if (!Utility.isEmpty(accountResponse) && accountResponse.isSubscribable()
&& !Utility.isEmpty(accountResponse.getAccountStatus())
&& accountResponse.getAccountStatus().equalsIgnoreCase("FREEVIEW")) {
return accountResponse;
}
}
return accountResponse;
}
Test Class
#Test(expected = ServiceException.class)
public void test_searchAccessID_3_sample() throws Exception {
AccessIDSearchRequest request = new AccessIDSearchRequest();
CommonData commonData = new CommonData();
commonData.setAppName("IDSE");
commonData.setLoginId("qay_slid_sr1281");
request.setCommonData(commonData);
request.setSearchtype("accountId");
request.setSearchvalue("qay_slid_sr1281");
request.setMode("abc");
SearchAccessIdContent content = new SearchAccessIdContent();
AccountResponse accountResponse = new AccountResponse();
accountResponse.setAccountStatus("Sucess");
accountResponse.setSubscribable(true);
Mockito.when(helper.getAccountStatus(accessIDResponse)).thenReturn(accountResponse);
Mockito.when(service.checkAccountStatus(request)).thenReturn(accountResponse);
service.searchAccessID(header, request);
}
Your mocks are not properly configured.
When you call
service.searchAccessID(header, request);
it was make the underlying call
checkAccountStatus(request);
(which is correctly mocked and returns accountResponse), but this one does instanciate its result object, so your first mock will never be triggered.
Updating your first mock to something more permissive will probably fix your problem
Mockito.when(helper.getAccountStatus(any(AccessIDSearchResponse.class))).thenReturn(accountResponse);
To be honest, your code is hardly testable because you instanciate too many objects everywhere. Going for mocks here will be a pain in the future when you refactor something. If I were you I would rewrite this piece of code using a TDD approach and favorizing more testable patterns.
Hi I am working on a project and using PrintWriter class for opening and writing in the file. But when I am writing the test case for same it gives following error at Line 153
Wanted but not invoked:
mockPrintWriter.println("ID url1
");
-> at x.y.z.verify(ProcessImageDataTest.java:153)
Actually, there were zero interactions with this mock.
Code: (Uses Lombok Library)
ProcessImageData.java
#Setter
#RequiredArgsConstructor
public class ProcessImageData implements T {
private final File newImageDataTextFile;
#Override
public void execute() {
LineIterator inputFileIterator = null;
try {
File filteredImageDataTextFile = new File(filteredImageDataTextFilepath);
PrintWriter writer = new PrintWriter(newImageDataTextFile);
inputFileIterator = FileUtils.lineIterator(filteredImageDataTextFile, StandardCharsets.UTF_8.displayName());
while (inputFileIterator.hasNext()) {
if(someCondition)
**Line51** writer.println(imageDataFileLine);
//FileUtils.writeStringToFile(newImageDataTextFile, imageDataFileLine + NEWLINE, true);
}
}
} catch (Exception e) {
} finally {
LineIterator.closeQuietly(inputFileIterator);
**LINE63** writer.close();
}
}
ProcessImageDataTest.java
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ProcessImageData.class, FileUtils.class, Printwriter.class })
public class ProcessImageDataTest {
private ProcessImageData processImageData;
private static final String FILTERED_IMAGE_DATA_TEXT_FILE_PATH = "filteredFilepath";
private File FILTEREDFILE = new File(FILTERED_PATH);
private static final File IMAGE__FILE = new File("imageFilePath");
private LineIterator lineIterator;
#Mock
private PrintWriter mockPrintWriter;
#Before
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
processImageData = new ProcessImageData(Palettes_file, FILTERED_PATH, IMAGE_FILE);
PowerMockito.mockStatic(FileUtils.class);
PowerMockito.whenNew(PrintWriter.class).withArguments(IMAGE_FILE).thenReturn(mockPrintWriter);
PowerMockito.when(FileUtils.lineIterator(FILTERED_FILE, StandardCharsets.UTF_8.displayName())).thenReturn(lineIterator);
PowerMockito.when(lineIterator.hasNext()).thenReturn(true, true, false);
}
#Test
public void testTaskWhenIDInDBAndStale() throws IOException {
PowerMockito.when(lineIterator.nextLine()).thenReturn(ID2 + SPACE + URL1, ID1 + SPACE + URL2);
processImageData.execute();
List<String> exepctedFileContentOutput = Arrays.asList(ID2 + SPACE + URL1 + NEWLINE);
verify(exepctedFileContentOutput, 1, 1);
}
#Test
public void testTaskWhenIDNotInDB() throws IOException {
PowerMockito.when(lineIterator.nextLine()).thenReturn(ID2 + SPACE + URL1, ID3 + SPACE + URL2);
processImageData.execute();
List<String> exepctedFileContentOutput = Arrays.asList(ID3 + SPACE + URL2 + NEWLINE);
verify(exepctedFileContentOutput, 1, 1);
}
private void verify(List<String> exepctedFileContentOutput, int fileWriteTimes, int fileReadTimes) throws IOException {
for (String line : exepctedFileContentOutput){
**Line153** Mockito.verify(mockPrintWriter, Mockito.times(fileWriteTimes)).print(line);
}
PowerMockito.verifyStatic(Mockito.times(fileReadTimes));
FileUtils.lineIterator(FILTERED_IMAGE_DATA_TEXT_FILE, StandardCharsets.UTF_8.displayName());
}
}
I am mocking a new operator for PrintWriter also, injecting using beans. What is the mistake I am doing?? I am stuck on it from long time and not getting the error?
Any help is appreciated.
Updated :
I did changes suggested below and updated the code, but now I get the error:
Wanted but not invoked: mockPrintWriter.print("ASIN2 url1 "); ->
at softlines.ctl.ruleExecutor.tasks.ProcessImageDataTest.verify(ProcessImageDataTest.java:153)
However, there were other interactions with this mock: -> at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(ProcessImageData.java:51) ->
at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(ProcessImageData.java:51) ->
at softlines.ctl.ruleExecutor.tasks.ProcessImageData.execute(ProcessImageData.java:58) –
I see 3 issues in your test:
You don't try to mock the correct constructor, indeed in the method execute, you create your PrintWriter with only one argument of type File while you try to mock the constructor with 2 arguments one of type File and the other one of type String.
So the code should rather be:
PowerMockito.whenNew(PrintWriter.class)
.withArguments(IMAGE_FILE)
.thenReturn(mockPrintWriter);
To be able to mock a constructor you need to prepare the class creating the instance which is ProcessImageData in this case, so you need to add ProcessImageData.class in the annotation #PrepareForTest. (I'm not sure ProcessImageDataTest.class is needed there)
The field lineIterator should be annotated with #Mock.
Instead of verifying print with a new line, you should verify directly println without new line it is much less error prone.
I simplified your code to show the idea.
Assuming that ProcessImageData is:
public class ProcessImageData {
private final File newImageDataTextFile;
public ProcessImageData(final File newImageDataTextFile) {
this.newImageDataTextFile = newImageDataTextFile;
}
public void execute() throws Exception{
try (PrintWriter writer = new PrintWriter(newImageDataTextFile)) {
LineIterator inputFileIterator = FileUtils.lineIterator(
newImageDataTextFile, StandardCharsets.UTF_8.displayName()
);
while (inputFileIterator.hasNext()) {
writer.println(inputFileIterator.nextLine());
}
}
}
}
My unit test would then be:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ProcessImageData.class, FileUtils.class})
public class ProcessImageDataTest {
private File file = new File("imageFilePath");
private ProcessImageData processImageData;
#Mock
private PrintWriter mockPrintWriter;
#Mock
private LineIterator lineIterator;
#Before
public void init() throws Exception {
MockitoAnnotations.initMocks(this);
processImageData = new ProcessImageData(file);
PowerMockito.whenNew(PrintWriter.class)
.withArguments(file)
.thenReturn(mockPrintWriter);
PowerMockito.mockStatic(FileUtils.class);
PowerMockito.when(
FileUtils.lineIterator(file, StandardCharsets.UTF_8.displayName())
).thenReturn(lineIterator);
PowerMockito.when(lineIterator.hasNext()).thenReturn(true, true, false);
}
#Test
public void testExecute() throws Exception {
PowerMockito.when(lineIterator.nextLine()).thenReturn("Foo", "Bar");
processImageData.execute();
Mockito.verify(mockPrintWriter, Mockito.times(1)).println("Foo");
Mockito.verify(mockPrintWriter, Mockito.times(1)).println("Bar");
}
}
For more details please refer to How to mock construction of new objects.
how can I add verification in unit test for writer.close?
One way could be to simply check that close() at be called once by adding the next line to your unit test:
Mockito.verify(mockPrintWriter, Mockito.times(1)).close();
Your construction of the PrintWriter doesn't match the mock. You told PowerMockito to return your mock like this:
PowerMockito.whenNew(PrintWriter.class).withArguments(IMAGE_FILE , StandardCharsets.UTF_8.name()).thenReturn(mockPrintWriter);
So you would have to say:
new PrintWriter(IMAGE_FILE, "UTF-8"); // 2 arguments
But instead in your execute method in the code that is being tested, you do:
PrintWriter writer = new PrintWriter(newImageDataTextFile); // only 1 argument
So you either need to change the PowerMockito withArguments clause, or you need to add "UTF-8" to the constructor invocation in the execute method.