I have test and class under test, which uses time in file name.
Test code:
SimpleDateFormat simpleDateFormatTimestamp = new SimpleDateFormat("yyMMddHHmmss");
String outputpath= inboundDir+inboundFilePrefix+simpleDateFormatTimestamp.format(new Date())+".txt";
PowerMockito.whenNew(File.class).withArguments(outputpath).thenReturn(outputFileToInboundDir);
Class under test Code:
File outputFile=new File(inboundDir+inboundFilePrefix+simpleDateFormatTimestamp.format(new Date())+".txt");
Also in test and class under test, i have other new file calls so i am not able to use withAnyArguments mocking. when i use withAnyArguments only one mock gets returned for all the new file calls.
My test case pass sometime and fails other times depending on test and class under test runs in same second ("yyMMddHHmmss") or not.
How do i remove this test failure, when class and test execute in different second.
Thanks
This is one possible solution.
String outputpath= inboundDir+inboundFilePrefix+simpleDateFormatTimestamp.format(new Date())+".txt";
PowerMockito.whenNew(File.class).withAnyArguments().thenAnswer(invocation -> {
String firstArgument = (String) invocation.getArguments()[0];
// do a pattern matching for firstArgument with a regex containing date in it.
// if its true then return outputpath
// else return something else
});
We could have used ArgumentCaptor but, PowerMockito.whenNew doesn't support that.
The Workaround which worked for me is as below.
Since i had only one such call in test, i removed variable part simpleDateFormatTimestamp.format(new Date())+".txt"
Now if i do below it worked fine.
String outputpath= inboundDir+inboundFilePrefix;
PowerMockito.whenNew(File.class).withArguments(startsWith(outputpath)).thenReturn(outputFileToInboundDir);
startsWith Matcher is available in org.mockito.Mockito
Related
I cloned existing project, where are some unit tests in JUnit-4.12. These tests are launched after every push to remote depository and they will end successfuly, but when I run them on my local machine in eclipse, they will end with ComparisonFailure.
org.junit.ComparisonFailure expected:<xy> but was:<xy>
With this error will end every test, where I'm trying to compare sent json with existing json file.
Test:
#Test
public void calculateSignedCasesView() throws JsonProcessingException {
Case case1 = prepareCase();
getEm().persist(case1);
SignedCasesViewFilter filter = new SignedCasesViewFilter(new LinkedHashSet<String>(Arrays.asList("testCode")), new Date(0), new Date(0));
SignedCasesView view = reportService.calculateSignedCasesView(filter);
String actual = getObjectMapper().writeValueAsString(view);
String expected = readToString("signedCasesReportView01.json");
Assert.assertEquals(expected, actual);
}
When I look on result, there are highlighted initial spaces of every row.
Result:
I tried copy this result to MS Word to look, if there aren't any non-breaking spaces (discussed here), but all spaces are ordinary. Or I tried to run tests with different encoding, but nothing works.
If the tests work on the repository and they don't work on your local machine I guess there is some difference in the encoding or in the way you produce the json. You haven't shown for example readToString function or the signedCasesReportView01.json file which may be different on the repository and in your local environment. My guess would be new lines which is the most common problem in different environments and when I look in your test cases there aren't any other special characters.
For example it often happens when you copy files to git repository and it is modified by the config core.autocrlf and it automatically changes \r\n from your local windows machine to \n because it is unix on the other side. And even the commited file might not show difference in the client but they can be actually different. Compare the byte streams or line by line and you should be able to spot the difference.
This may be a line endings issue as Veselin suggested. Perhaps consider a semantic comparison where the exact format of the file is not necessary.
You can achieve this with ModelAssert - https://github.com/webcompere/model-assert
String actual = getObjectMapper().writeValueAsString(view);
String expected = readToString("signedCasesReportView01.json");
assertJson(actual)
.isEqualTo(expected);
Where they are not the same, this will also output the paths that are different.
I am trying to call the BuiltIN keyword 'Set Test Variable' in java. The reason being is that I want to declare some variables that are read in from the test data.
I have searched and tried many times without success. I have something like:
Selenium2Library selenium2Library = Selenium2Library.getLibraryInstances();
String[] test = new String[1];
test[0] = "hello";
selenium2Library.runKeyword("Log", test);
This gives a null pointer exception error. I get the same error when instead of Log I use Set Test Variable, which is what I want. Any help is much appreciated.
My process simply add some content to the system variable PATH. Actually I'm doing this with a Process that use the setx.exe:
public void changePath(String newPath ) {
String path = System.getenv("PATH") + ";";
String[] cmd = new String[]{"C:\\Windows\\System32\\setx.exe", "PATH",
path+newPath, "-m"};
ProcessBuilder builder = new ProcessBuilder(cmd);
...
}
So I tried to write a test case to it.
Class UpdatePathTest {
#Test
public void testUpdatePath() {
//call the method that update the path
changePath("C:\\somebin");
assertTrue(System.getenv("PATH").contains("C:\\somebin")); //fails
// ProcessBuilder with command String[]{"cmd", "/C", "echo", "%PATH%"}; will fail too.
//and the above in a new Thread will fail too.
}
}
So, is there any way to get the new PATH value? Writing the new path is the only option, because I'm developing a jar that will install a desktop application.
I'm not sure changing the path is a good idea in a unit test. What if the test fails? You will have to make sure you do all the relevant tidy up.
Consider inverting your dependencies and use dependency injection.
This article explains it quite well I think.
So instead of having a method that does:
public void method() {
String path = System.getenv("PATH") + ";";
//do stuff on path
}
consider doing:
public void method(String path) {
//do stuff on path
}
which allows you to stub the path. If you cannot change the signature of the method then consider using the factory pattern and using a test factory to get the path.
EDIT: after update to question
What you have to think about here is what you are testing. When you call C:\Windows\System32\setx.exe you have read the API docs and are calling it with the correct parameters. This is much like calling another method on a java API. For example if you are manipulating a list you "know" it is zero based. You do not need to test this you just read the API and the community backs you up on this. For testing changePath I think you probably what to test what is going into ProcessBuilder. Again you have read the API docs and you have to assume that you are passing in the correct variables. (See //1 at bottom) And again you have to assume that ProcessBuilder works properly and that the Oracle (or most likely Sun) guys have implemented it to the API documents.
So what you want to do is check that you are passing variables to ProcessBuilder that match the specification as you understand it. For this you can mock ProcessBuilder and then verify that you are passing the correct parameters and calling the correct method on this class.
In general it is a hard one to test because you don't want to test the windows functions but want to test java's interaction with them.
//1 The main problem I have had with calling this external commands is understanding the API documents correctly or setting up the command. Usually you have to get the command line out and check that you are using methods correctly (esp cmd functions). This can mean that you work out how to use the cmd function, code it into ProcessBuilder and then write a test (or vice versa on the ProcessBuilder/test) Not the ideal way but sometimes documents are hard to understand.
I've tried various things and googled multiple hours but couldn't find a solution to my problem.
I'm using the Quality Center OTA API via Com4j to let my programm communicate with QC.
It works pretty good, but now I've stumbed upon this problem:
I want to add new parameters to a test case in "Test Plan" using my programm.
If I used VB it would work somehow like this:
Dim supportParamTest As ISupportTestParameters
Set supportParamTest = TDConnection.TestFactory.Item(5)
Set testParamsFactory = supportParamTest.TestParameterFactory
Set parameter = testParamsFactory.AddItem(Null)
parameter.Name = name
parameter.Description = desc
parameter.Post
Set AddTestParameter = parameter
The important part is the call of AddItem() on the TestParameterFactory. It adds and returns a parameter that you then can give a name and description. In VB the AddItem-method is given Null as argument.
Using Java looks similar at first:
First I establish the connection and get the TestFactory (and the list of test cases).
QcConnect qc = new QcConnect(server, login, password, domain, project);
ITDConnection qcConnection = qc.getConnection();
ITestFactory qcTestFactory = qcConnection.testFactory().queryInterface(ITestFactory.class);
IList qcTestList = qcTestFactory.newList("");
qcTestList contains all tests from Test Plan.
ITest test = qcTestList.item(1);
ISupportTestParameters testParam = test.queryInterface(ISupportTestParameters.class);
ITestParameterFactory paramFac = testParam.testParameterFactory().queryInterface(ITestParameterFactory.class);
No problem so far. All the "casts" are successful.
Now I want to call the addItem-method on the TestParameterFactory, just like in VB.
Com4jObject com = paramFac.addItem(null);
This doesn't work. The addItem()-method always returns null. I've tried various arguments like a random String, a random Integer, the test case's ID, etc. Nothing works.
How do I use this method correctly in Java?
Or in general: How do I add parameters to existing test cases in Test Plan using Java?
Quick note: Adding test cases to Test Plan works very similar to adding parameters to this test cases. You also use a factory and a addItem-method. In VB you give null as parameter, but in Java you use a String (that's interpreted as the name of the test). But as I said, that does not work in here.
I have finally found the answer to this:
Com4jObject obj = iTestParameterFactory.addItem(new Variant(Variant.Type.VT_NULL));
iTestParameter = obj.queryInterface(ITestParameter.class);
iTestParameter.name("AAB");
iTestParameter.defaultValue("BBB");
iTestParameter.description("CCC");
iTestParameter.post();
Regards.
What you want to pass to AddItem is DBNull and not null.
In VB it's the same, but in Java & .NET it's not.
Not sure how DBNull is exposed using Com4J.
Read more about this at this site.
//C# code snippet -> You have to use DBNull.Value instead of null
//Add new parameter and assign values
TestParameter newParam =(TestParameter)tParamFactory.AddItem(DBNull.Value);
newParam.Name = "ParamNew";
newParam.DefaultValue = "DefaultValue";
newParam.Description = "AnyDesc";
newParam.Post();
I have an #Test method with invocationCount=3.
Each time this method is run, there is a call for preparing some doc into another method.
All it's working GREAT when the #Test is run for the 1st time.
The doc is succesfully found and loaded:
final DocumentRegistryResource documentRegistryResource =
RestClientFactory.getInstance().createDocumentRegistryResource(
getUserRestAuth());
final File importFile = new File(
this.getClass().getResource("/documents-template-test.xml").getFile());
BUT, at the 2nd and 3rd invocation, i receive a null exception:
this.getClass().getResource("/documents-template-test.xml")
is no longer found.
Can anyone explain me WHY? The original file is on the same place, nothing was moved
during the 1st time invocation...
Do you close your file in the cleanup phase? Otherwise, your file might be locked on the second invocation of your test.
Also, be careful with the use of the final keyword combined with a test case. Using static or final can break a correct initialization or cleanup.