I working on testing some static classes using PowerMockito, and sometimes the test fail, in order to overcame this issue a create a customize JUnit Rule to re-run the failure tests. The rule works fine but whenever the test is re-executed , it's fail again but this time at the instruction mockStatic(StaticClass.class) which throw the exception org.powermock.api.mockito.ClassNotPreparedException.
Why the #PrepareForTest is executed only at the first run but not when the test is re-run.
I think the problem was caused by PowerMock when he creat a deep clone of my rules. To overcome this problem I used JUnit rule chain :
RuleChain.outerRule((base, description) -> {
try {
final FrameworkMethod method = new FrameworkMethod(
description.getTestClass().getMethod(description.getMethodName()));
return (new PowerMockRule()).apply(base, method, this);
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(e);
}
}).around(myRetryRule).around(otherRules).....
A more generale soulution for this problem is proposed here MergedRule, 2, 3.
Related
I am getting InvalidUseOfMatchersException on a different test than the one using Matchers
The below two tests are running fine individually but when running together, after the first test passes successfully, second test is failing and throwing InvalidUseOfMatchersException pointing to first test
#Test(expected = InputException.class)
public void shouldThrowExceptionWhenInputNull() {
calculator.calculateA(any(), any(), any(),eq(null));
}
#Test
public void testCalculateB() {
assertTrue(BigDecimal.valueOf(8000).compareTo(calculator.calculateB(12)) == 0);
}
This is the exception in stack trace
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:
TestClass.shouldThrowExceptionWhenInputNull
According to the exception, first test should fail but its passing and second test is failing. Individually both these tests are passing successfully
calculator.calculateA(any(), any(), any(), eq(null));
This isn't a valid use of Matchers. Mockito only uses any and eq when used with when or verify, as a means of matching invocations that tell Mockito what to return or what calls should have been recorded. You'll need to call calculateA with specific values, such as calculator.calculateA(1, 2, 3, null);.
Mockito matchers work via side effects, so the only time that Mockito can throw an exception is the next time you interact with Mockito. This might be another method, but you can help ensure that those are local by using MockitoRule, MockitoJUnitRunner, or by adding a call to validateMockitoUsage from an #After method:
#After public void validateMockito() {
Mockito.validateMockitoUsage();
}
I ran into a dilemma with making a test pass if it times out.
#Test(timeout=1, expected=Exception.class)
public void testMovesToSolveMaximum() {
PuzzleSolver pS = createSimplePuzzleSolver(maximumPuzzleStateA, maximumPuzzleStateB);
PuzzleState goal = new SimplePuzzleState();
goal.configureState(maximumPuzzleStateB);
checkThatComputedSolutionIsCorrect(pS, goal);
}
However, the test case fails due to timeout even though I specified that is the expected result.
If I understand the question correctly then you are observing the specific behavior due to the way that the default JUnit runner is evaluating the whole test:
After realizing that there is a timeout set on your test method it runs it in a different thread and is waiting for the result. As the timeout in your example is set to 1[ms] I believe that it reaches the timeout before the test actually finishes which makes the runner throw the timeout exception (that is indeed a java.lang.Exception) which you thought needed to be caught by the expected attribute in the Test annotation. But the attribute expected on the Test annotation is evaluating only the exceptions thrown from the test method and not from the timeout checking mechanism. In other words the expected exception mechanism is not working for the timeout exception throw by the f/w and not by a test.
You can explore this yourself starting in BlockJUnit4ClassRunner class in JUnit (relevant part to start from. NOTE: it is not so easy to go over the code and understand the flow...):
protected Statement methodBlock(FrameworkMethod method) {
Object test;
try {
test = new ReflectiveCallable() {
#Override
protected Object runReflectiveCall() throws Throwable {
return createTest();
}
}.run();
} catch (Throwable e) {
return new Fail(e);
}
Statement statement = methodInvoker(method, test);
statement = possiblyExpectingExceptions(method, test, statement);
statement = withPotentialTimeout(method, test, statement);
statement = withBefores(method, test, statement);
statement = withAfters(method, test, statement);
statement = withRules(method, test, statement);
return statement;
}
In my webdriver script I have the three methods
setup, test and tearDown
following the junit convention.
In the test method I have few asserts like this
#Test
public void testStudentHome() throws Exception {
String classCode = "I6OWW";
Utilities.studentSignin(driver, baseUrl);
assertEquals(true, sth.openNotification());
assertEquals("My Scores", sth.myScores(true));
}
The sth is the PageObject on which I am performing the tests and that I have created in the setup method.
I am calling all these three methods from a main method like this:
public static void main(String[] args) {
StudentHomeTest sht = new StudentHomeTest();
try {
sht.setup();
sht.testStudentHome();
sht.tearDown();
} catch (Exception ex) {
Logger.getLogger(StudentHomeTest.class.getName()).log(Level.SEVERE, null, ex);
sht.tearDown();
}
}
Now while running the test if some assertion fails the test method should (this is what I expect) throw an exception and the main method should call the tearDown method. But this does not happen. and the browser window continues to stay there.
I am using the netbeans ide for running the test.
following the junit convention
If you follow the jUnit convention, then you will know that teardown methods belong in the #After method as this method will always run after your tests.
create a new method with the #After jUnit annotation.
#After
public void tearDown() {
sht.tearDown();
}
Edit
You know what, I believe that you are running into a classic issue of assertEquals in jUnit.
Stolen from this answer...:
JUnit calls the .equals() method to determine equality in the method assertEquals(Object o1, Object o2).
So, you are definitely safe using assertEquals(string1, string2). (Because Strings are Objects)
--
Instead of using assertEquals on these calls, use assertTrue() instead.
assertTrue(sth.openNotification());
assertTrue("My Scores".equals(sth.myScores(true)));
AssertionError doesn't extend Exception - it's a Throwable.
But in any case, you should have
try {
sht.setup();
sht.testStudentHome();
} finally {
sht.tearDown();
}
No need for a catch block. main can throw Exception.
I am new to JUnit, but this is what I am trying to do:
generate data with my DataGenerator class;
instantiate a test class MyTestClass
pass to MyTestClass the test data generated data (first step)
run the test
collect TestResult result
With the above, all works, but I cannot see any timing information (time it took to complete the test) at the TestResult object. Anything being done wrong here ?
The approach above is because I need to run this on other test classes using the same data.
DataGenerator testData = new DataGenerator();
MyTestClass myTestClass = new MyTestClass("mytestmethod");
myTestClass.setBaseLine(testData);
try {
TestResult testResult = myTestClass.run();
System.out.println(testResult.wasSuccessful());
} catch (Throwable ex) {
Logger.getLogger(TestSupervisor.class.getName()).log(Level.SEVERE, null, ex);
}
JUnit 4 has a timeout annotation that will fail the test if the test too long.
//this test will fail if it takes longer than 1 sec
#Test(timeout = 1000)
public void myTest(){
...
}
I think you can get around the DataGenerator issue by using a better TestFixture.
If all of your tests that use the DataGenerator are in the same test class, you can use the #BeforeClass and #AfterClass annotations to set up and tear down data that is used across tests. (those methods with those annotations are called only once before/after all the tests are run).
If writing a Java unit test with mocking using JMock, should we use
Mockery context = new Mockery()
or
Mockery context = new JUnit4Mockery()
What is the difference between the two, and when should we use which?
#Rhys It's not the JUnit4Mockery that replaces the need to call assertIsSatisfied, its the JMock.class (combined with the #RunWith). You wont need to call assertIsSatisfied when you create a regular Mockery.
The JUnit4Mockery translates errors.
By default, expectation exceptions are reported in Junit as ExpectationError, so for example, using
Mockery context = new Mockery();
you'll get
unexpected invocation: bar.bar()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
and using,
Mockery context = new JUnit4Mockery();
you'll get
java.lang.AssertionError: unexpected invocation: bar.bar()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
what happened before this: nothing!
The JUnit4Mockery converted the ExpectationError to an java.lang.AssertionError which JUnit deals with. Net result is that it'll show up in your JUnit report as an failure (using JUnit4Mockery) rather than an error.
When using JMock with JUnit 4, you can avoid some boilerplate code by taking advantage of the JMock test runner. When you do this, you must use the JUnit4Mockery instead of the regular Mockery.
Here is how you'd structure a JUnit 4 test:
#RunWith(JMock.class)
public void SomeTest() {
Mockery context = new JUnit4Mockery();
}
The main advantage is there is no need to call assertIsSatisfied in each test, it is called automatically after each test.
Better yet, per http://incubator.apache.org/isis/core/testsupport/apidocs/org/jmock/integration/junit4/JUnitRuleMockery.html use #Rule and avoid #RunWith which you might need for some other system:
public class ATestWithSatisfiedExpectations {
#Rule
public final JUnitRuleMockery context = new JUnitRuleMockery();
private final Runnable runnable = context.mock(Runnable.class);
#Test
public void doesSatisfyExpectations() {
context.checking(new Expectations() {
{
oneOf(runnable).run();
}
});
runnable.run();
}
}