MockWebServer: llegalStateException: start() already called - android-testing

I try to run a test with MockWebServer.
I would like to make a UI test with mocked response, so I could test for valid\invalid UI changes like logging in, or showing error in a login API.
However, each and every time I ran the code I got the following exception:
java.lang.IllegalStateException: start() already called
Code:
#RunWith(AndroidJUnit4.class)
public class UITestPlayground {
String testUrl = "http://testurl.com/";
MockWebServer server = new MockWebServer();
#Rule
public IntentsTestRule<LoginActivity> mIntentsRule = new IntentsTestRule<>(LoginActivity.class);
#Before
public void beforeHelper() throws IOException {
TestHelper.removeUserAndTokenIfAny(mIntentsRule.getActivity());
URLS.baseUrl = testUrl;
server.url(URLS.baseUrl);
//try to shutting down the server JUT IN CASE...
server.shutdown();
server.start();
}
#After
public void afterHelper() throws IOException {
server.shutdown();
}
#Test
public void invalidLoginDueNotValidJSONResponse() {
server.enqueue(new MockResponse().setBody("Something not valid JSON response"));
String emailToBeTyped = "tester#tester.com";
String passToBeTyped = "passtest";
ViewActions.closeSoftKeyboard();
// Type text and then press the button.
onView(withId(R.id.login_email_edit)).perform(typeText(emailToBeTyped));
ViewActions.closeSoftKeyboard();
onView(withId(R.id.login_pass_edit)).perform(typeText(passToBeTyped));
ViewActions.closeSoftKeyboard();
onView(withId(R.id.log_in_btn)).perform(click());
//TODO: check on valid error message appearing
}
}
What am I doing wrong? The .start() only called once, I even .shutdown() just in
case... I don't understand how could it called more than once.
Thanks in advance.

In the original example at github I have found that the order is reversed.
You actually start the server, THEN sets it's url.
And not setting the url then starting the server.
Interesting.

Related

Jenkins API to retrieve a build log in chunks

For a custom monitoring tool I need an API (REST) to fetch the console log of a Jenkins build in chunks.
I know about the /consoleText and /logText/progressive{Text|HTML} APIs, but the problem with this is that sometimes, our build logs get really huge (up to a few GB). I have not found any way using those existing APIs that avoids fetching and transferring the whole log in one piece. This then normally drives the Jenkins master out of memory.
I already have the Java code to efficiently fetch chunks from a file, and I have a basic Jenkins plugin that gets loaded correctly.
What I'm missing is the correct extension point so that I could call my plugin via REST, for example like
http://.../jenkins/job/<jobname>/<buildnr>/myPlugin/logChunk?start=1000&size=1000
Or also, if that is easier
http://.../jenkins/myPlugin/logChunk?start=1000&size=1000&job=<jobName>&build=<buildNr>
I tried to register my plugin with something like (that code below does not work!!)
#Extension
public class JobLogReaderAPI extends TransientActionFactory<T> implements Action {
public void doLogChunk(StaplerRequest req, StaplerResponse rsp) throws IOException {
LOGGER.log(Level.INFO, "## doLogFragment req: {}", req);
LOGGER.log(Level.INFO, "## doLogFragment rsp: {}", rsp);
}
But I failed to find the right encantation to register my plugin action.
Any tips or pointers to existing plugins where I can check how to register this?
This was indeed more simple than I expected :-) It as always: once one understands the plugin system, it just needs a few lines of code.
Turns out all I needed to do was write 2 very simple classes
The "action factory" that get's called by Jenkins and registers an action on the object in question (in my case a "build" or "run"
public class ActionFactory extends TransientBuildActionFactory {
public Collection<? extends Action> createFor(Run target) {
ArrayList<Action> actions = new ArrayList<Action>();
if (target.getLogFile().exists()) {
LogChunkReader newAction = new LogChunkReader(target);
actions.add(newAction);
}
return actions;
}
The class the implements the logic
public class LogChunkReader implements Action {
private Run build;
public LogChunkReader(Run build) {
this.build = build;
}
public String getIconFileName() {
return null;
}
public String getDisplayName() {
return null;
}
public String getUrlName() {
return "logChunk";
}
public Run getBuild() {
return build;
}
public void doReadChunk(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {

How to detect when Vaadin FileDownloader succeeds or fails

I have Vaadin 7 code to give the user an option to download a file:
Button btnDownloadResults = new Button("Download Results", FontAwesome.CLOUD_DOWNLOAD);
resource = new StreamResource(new MyStreamResource(), suggestedSaveAsFilename);
new FileDownloader(resource).extend(btnDownloadResults);
I would like to trigger code when the download has succeeded, or even if the download manages to start. Uses for this include closing a window, starting a progress spinner, or incrementing a download count.
Unlike the Vaadin Upload component, the FileDownloader does not have any listeners for finding out when a file download fails, succeeds, or starts.
Here is a simplified version of my StreamResouce subclass:
public class MyStreamResource implements StreamSource {
#Override
public InputStream getStream() {
String filename = /* code to determine the filename */;
try {
final File results = new File(FilenameUtils.normalize(filename));
return new FileInputStream(results);
} catch (FileNotFoundException fnfe) {
String errorMsg = "Cannot download results. Try again later, or contact your sysadmin.";
Utilities.showError(errorMsg);
return null;
} catch (Exception e) {
Utilities.logAndShowException(e);
return null;
}
}
}
Note that the getStream method returns before the user has even been prompted where to save the file (which they can choose to cancel.) So I can't trigger anything from inside that method.
One suggestion I got was to subclass the FileDownloader as follows:
FileDownloader fileDownloader = new FileDownloader(fileInputStream) {
private static final long serialVersionUID = -4584979099145066535L;
#Override
public boolean handleConnectorRequest(VaadinRequest request, VaadinResponse response, String path) throws IOException {
boolean result = super.handleConnectorRequest(request, response, path);
if (result) {
/* YOUR LOGIC GOES HERE */
}
return result;
}
} ;
Again, this fires too soon (and the boolean result is always true, even if my StreamSource returns null.)
Any suggestions?
After more research I believe the answer is that there is no simple way to get this information from the FileDownloader.
The difficulty appears to be a consequence of the way the FileDownloader is designed. From the FileDownloader docs:
"Download should be started directly when the user clicks e.g. a Button without going through a server-side click listener to avoid triggering security warnings in some browsers."
Because there is no round-trip back to the web server, there is no place to respond when the download fails, starts, or succeeds.
Some vague (and possibly bad) ideas for a workaround:
Have JS post some kind of asynchronous notification to the web
server, letting it know what happened. (Using JMS or Ajax?)
If there was some kind active process on the backend involved with transferring the file, it
would know when the transfer happened.
But the short answer seems to be there is no built-in way in Vaadin to do it.

CodenameOne Connection Request hangs when repeated

I have the following Codename One code for accessing a network resource. It is almost an exact copy of the Codename One tutorial for this use case.
public void executeRequest(){
String url = "http://www.random.net";
InfiniteProgress prog = new InfiniteProgress();
final Dialog dlg = prog.showInifiniteBlocking();
ConnectionRequest r = new ConnectionRequest() {
#Override
protected void postResponse() {
//handle changes to my form
}
#Override
protected void readResponse(InputStream input)
throws IOException {
//handle parsing data
}
#Override
protected void handleIOException(IOException err) {
super.handleIOException(err);
}
};
r.setUrl(url);
r.setPost(false);
r.addArgument("arg", "2");
r.setDuplicateSupported(true);
r.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueue(r);
}
The first time I run it - no problem. If I try to "refresh" my data by calling the same method over again, the app will hang up with the InfiniteProgress dialog spinning forever. Its almost like the first network request is not ever really completing, and then the second one kind of conflicts. Any ideas what I'm doing wrong?
By default duplicate requests to the exact same URL are disabled, try invoking setDuplicatesSuppotred(true) on the connection request.
For future reference, what fixed this for me was to use
NetworkManager.getInstance().addToQueueAndWait(r);
instead. That cleared up most of my problems.
I stucked with the same problem and none of solutions worked. However, I did it this way:
final NetworkManager nm = NetworkManager.getInstance();
nm.setTimeout(3000);
then
protected void postResponse() {
...
nm.shutdown();
}
and call was made as
nm.addToQueueAndWait(request);
Maybe the fact that NetworkManager was made final did the job, but I put "shutdown" just for sure. It worked for me

Struts2 Junit4 tests accumulate JSON responses with every action execution

I've written a few Junit4 tests, which looks like this :
public class TestCampaignList extends StrutsJUnit4TestCase<Object> {
public static final Logger LOG = Logger.getLogger(TestCampaignList.class.getName());
#Before
public void loginAdmin() throws ServletException, UnsupportedEncodingException {
request.setParameter("email", "nitin.cool4urchat#gmail.com");
request.setParameter("password", "22");
String response = executeAction("/login/admin");
System.out.println("Login Response : " + response);
}
#Test
public void testList() throws Exception {
request.setParameter("iDisplayStart", "0");
request.setParameter("iDisplayLength", "10");
String response = executeAction("/campaign/list");
System.out.println("Reponse : " + response);
}
}
Both actions return JSON results and executeAction javadoc says :
For this to work the configured result for the action needs to be FreeMarker, or Velocity (JSPs can be used with the Embedded JSP plugin)
Seems like it's unable to handle JSON results and hence, the second action execution shows accumulated result, such that result_for_second_action= result1 concatenate result2
Is there a solution to get the executeAction() return the actual JSON response, rather than concatenating JSON responses from all previous executions.
This is happening because you are executing action in #Before method. In that way the setUp method of StrutsJUnit4TestCase is not getting called in between your loginAdmin and test method and you previous request parameters are passed to it again. You can call setUp method by yourself in your tests method.
In your case you can actually call initServletMockObjects method to create new mock servlet objects such as request.
#Test
public void testList() throws Exception {
setUp();
// or
// initServletMockObjects();
request.setParameter("iDisplayStart", "0");
request.setParameter("iDisplayLength", "10");
String response = executeAction("/campaign/list");
System.out.println("Reponse : " + response);
}

ELMAH - Using custom error pages to collecting user feedback

I'm looking at using ELMAH for the first time but have a requirement that needs to be met that I'm not sure how to go about achieving...
Basically, I am going to configure ELMAH to work under asp.net MVC and get it to log errors to the database when they occur. On top of this I be using customErrors to direct the user to a friendly message page when an error occurs. Fairly standard stuff...
The requirement is that on this custom error page I have a form which enables to user to provide extra information if they wish. Now the problem arises due to the fact that at this point the error is already logged and I need to associate the loged error with the users feedback.
Normally, if I was using my own custom implementation, after I log the error I would pass through the ID of the error to the custom error page so that an association can be made. But because of the way that ELMAH works, I don't think the same is quite possible.
Hence I was wondering how people thought that one might go about doing this....
Cheers
UPDATE:
My solution to the problem is as follows:
public class UserCurrentConextUsingWebContext : IUserCurrentConext
{
private const string _StoredExceptionName = "System.StoredException.";
private const string _StoredExceptionIdName = "System.StoredExceptionId.";
public virtual string UniqueAddress
{
get { return HttpContext.Current.Request.UserHostAddress; }
}
public Exception StoredException
{
get { return HttpContext.Current.Application[_StoredExceptionName + this.UniqueAddress] as Exception; }
set { HttpContext.Current.Application[_StoredExceptionName + this.UniqueAddress] = value; }
}
public string StoredExceptionId
{
get { return HttpContext.Current.Application[_StoredExceptionIdName + this.UniqueAddress] as string; }
set { HttpContext.Current.Application[_StoredExceptionIdName + this.UniqueAddress] = value; }
}
}
Then when the error occurs, I have something like this in my Global.asax:
public void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
var item = new UserCurrentConextUsingWebContext();
item.StoredException = args.Entry.Error.Exception;
item.StoredExceptionId = args.Entry.Id;
}
Then where ever you are later you can pull out the details by
var item = new UserCurrentConextUsingWebContext();
var error = item.StoredException;
var errorId = item.StoredExceptionId;
item.StoredException = null;
item.StoredExceptionId = null;
Note this isn't 100% perfect as its possible for the same IP to have multiple requests to have errors at the same time. But the likely hood of that happening is remote. And this solution is independent of the session, which in our case is important, also some errors can cause sessions to be terminated, etc. Hence why this approach has worked nicely for us.
The ErrorLogModule in ELMAH (version 1.1 as of this writing) provides a Logged event that you can handle in Global.asax and which you can use to communicate details, say via HttpContext.Items collection, to your custom error page. If you registered the ErrorLogModule under the name ErrorLog in web.config then your event handler in Global.asax will look like this:
void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
var id = args.Entry.Id
// ...
}

Resources