Here is the relevant code in my test:
private MockedStatic<MyDAO> myDAOStaticMock;
#Captor
ArgumentCaptor<SomeInput> someInputCaptor;
#Before
public void before() {
myDAOStaticMock = Mockito.mockStatic(MyDAO.class);
}
#After
public void after() {
myDAOStaticMock.close();
}
#Test
public void test() {
thingImTesting.methodThatCallsDaoStatically();
myDAOStaticMock.verify(() -> MyDao.staticMethod(someInputCaptor.capture()), times(2));
}
When I run this test in intellij, it almost always works. When it runs through our build system, it fails every time. The error is that there is 0 interaction with this mock.
What might be the problem with this particular verify, when all of the rest of my static checks work fine?
Edit: I was wrong about the reason for the issue and the static checks were not related. See my answer for more information.
I was wrong about the reason these tests failed in the build system. The unit test I wrote called DateTime.now() which has a different result depending on the timezone of where you are running the code. My build system was running the code in a different timezone, so the test failed in that context.
By being explicit about time zone in my unit test (e.g. DateTime.now().withZone(whatever)), I was able to fix the issue.
Related
I'm testing some methodA which has another one inside and I need to check that that methodB has not been called due to return.
If I run this test with debug, everything works correctly. But test fails as PowerMock runs it somewhere underhood.
My test:
#Test
public void incomingCall_dismissIncoming_incomingDataNull() throws Exception {
mIncomingCallData = null;
Whitebox.setInternalState(SUT, "mLastIncomingCallData", mIncomingCallData);
SUT.dismissIncoming();
verifyPrivate(SUT, times(0)).invoke("onIncomingCallDeclined");
}
The question is why is that and how can I test it? I know I don't need to test private methods, but I need it in this specific case.
I have simple Android application with some espresso tests.
I want to write some base class so all of my test classes will inherit its #beforeClass and #afterClass methods, but the problem is when I do it like code example below, JUnit doesn't see any tests at al. I got Empty test suite. message. What's the problem?
Code example:
public class RealmTest {
protected static Realm realm;
#BeforeClass
public static void beforeClass() {
realm = Realm.getDefaultInstance();
realm.setAutoRefresh(true);
}
#AfterClass
public static void afterClass() {
realm.close();
}
}
#RunWith(AndroidJUnit4.class)
public class MainActivityTest extends RealmTest {
#Rule
public IntentsTestRule<MainActivity> activityTestRule = new IntentsTestRule<>(MainActivity.class);
#Test
public void startedFine() {
assertNotNull(realm);
onView(withId(R.id.button)).perform(click());
intended(hasComponent(new ComponentName(getTargetContext(), EducationActivity.class)));
}
}
If I'll run all tests, tests from MainActivityTest won't run.
Thanks for your help, pls say if some additional info is needed.
Guessing: the JUnit environment is not looking for static methods. So maybe you simply drop that keyword from your base methods (guess you could keep your Realm static nonetheless; I assume you really only want one of those).
But then, another suggestion: don't use inheritance for test cases.
The point that makes test cases valuable to you is: they should quickly allow you to find and fix bugs in your production code.
But when your "setup" is hidden from your testcases - because things are not only happening in some #Before method ... but in a #Before method somewhere, in some different class ... well, that can seriously increase the time you will need to understand a failing testcase. Because: instead of just studying your test case, you find yourself digging around within test code in order to understand what exactly is happening besides the code in that failing test method itself!
Thus: be really careful to balancing "code duplication" versus "test case is easy to understand" aspects!
I have a class that makes native Windows API calls through JNA. How can I write JUnit tests that will execute on a Windows development machine but will be ignored on a Unix build server?
I can easily get the host OS using System.getProperty("os.name")
I can write guard blocks in my tests:
#Test public void testSomeWindowsAPICall() throws Exception {
if (isWindows()) {
// do tests...
}
}
This extra boiler plate code is not ideal.
Alternatively I have created a JUnit rule that only runs the test method on Windows:
public class WindowsOnlyRule implements TestRule {
#Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (isWindows()) {
base.evaluate();
}
}
};
}
private boolean isWindows() {
return System.getProperty("os.name").startsWith("Windows");
}
}
And this can be enforced by adding this annotated field to my test class:
#Rule public WindowsOnlyRule runTestOnlyOnWindows = new WindowsOnlyRule();
Both these mechanisms are deficient in my opinion in that on a Unix machine they will silently pass. It would be nicer if they could be marked somehow at execution time with something similar to #Ignore
Does anybody have an alternative suggestion?
In Junit5, There are options for configuring or run the test for specific Operating System.
#EnabledOnOs({ LINUX, MAC })
void onLinuxOrMac() {
}
#DisabledOnOs(WINDOWS)
void notOnWindows() {
// ...
}
Have you looked into assumptions? In the before method you can do this:
#Before
public void windowsOnly() {
org.junit.Assume.assumeTrue(isWindows());
}
Documentation: http://junit.sourceforge.net/javadoc/org/junit/Assume.html
Have you looked at JUnit assumptions ?
useful for stating assumptions about the conditions in which a test
is meaningful. A failed assumption does not mean the code is broken,
but that the test provides no useful information. The default JUnit
runner treats tests with failing assumptions as ignored
(which seems to meet your criteria for ignoring these tests).
If you use Apache Commons Lang's SystemUtils:
In your #Before method, or inside tests that you don't want to run on Win, you can add:
Assume.assumeTrue(SystemUtils.IS_OS_WINDOWS);
Presumably you do not need to actually call the Windows API as part of the junit test; you only care that the class which is the target of the unit test calls what it thinks is a the windows API.
Consider mocking the windows api calls as part of the unit tests.
I'm currently having some memory problems with some unit tests in a fairly large project of mine. Throughout my hair pulling and research today, I have come to realize that it appears to be related to objects not always being cleaned up as fast as I think they should be cleaned up. I started researching "cleanup mockito" and "cleanup junit" and came across a few blogs and forum posts about how to use #Before and #After (as well as their *Class versions) to do intense things that you don't want being done with every unit test. This got me to thinking about Mockito's #Mock and #InjectMocks annotations.
Can someone please describe to me in detail how the class variables below are being handled in memory during a maven build? Will the objects be created before, during, or after unit tests? Are the objects immediately destroyed after the last unit tests completes? Should I be using #After to set all the class variables to null?
Thanks many times over. Here's a sample of a test case I may use:
#RunWith(MockitoJUnitRunner.class)
public class thisCustomTest {
#Mock
MyCustomSpringBean myCustomerSpringBean;
#InjectMocks
MyBeanToTest myBeanToTest;
#Before
public void config() {
MockitoAnnotations.initMocks(this);
}
#Test
public void someTest() {
//code here
}
}
Just to do a quick wrap-up / summary at the end, my main question is whether or not I should be utilizing something like #After to clean up class variables, or should I simply leave those for Java's normal scope garbage collection...
My idea of cleanup:
#After
public void cleanup() {
mockedClassVariable = null;
injectedVariable = null;
}
JUnit creates a new instance of your unit test class before running each test method. Once the instance is created, its #Before annotated method(s) is (are) executed. Then the test method is executed. Then, whatever happened in the test method (success, failure or error), the #After annotated method(s) is (are) run.
So, in this particular case, MockitoAnnotations.initMocks(this) is executed before each test method, which creates a new mock each time, a new MyBeanToTest each time, and injects the mock into the bean to test.
Those beans will be eligible for GC, along with the test instance which references them, after the test method execution. Setting them to null in the cleanup method doesn't serve any purpose.
I have a Junit test class with multiple #Test methods in it that I need to run in order. If there is an exception thrown in a method I would like to stop entire test case and error out, but all of the rest of the test methods running.
public class{
#Test{
//Test1 method`enter code here`
}
#Test{
//Test2 method
}
#Test{
//Test3 method
}
}
If Test1 method fails then don't run other Tests
Note: All are independent tests
Unit tests should be designed to run independently of one another. The order of execution cannot be guaranteed. You should redesign your test class so that the order is not important.
Without further information it's hard to advise you specifically. But it may help to have an #before method, which checks for some precondition before running each test. If you included an Assume.assumeTrue(...) method call, then your test could be skipped if the condition fails?
As discribed here, JUnit 4.11 supports the ordered execution with the Annotation #FixMethodOrder, but the others are right, all tests should be independent of each other.
At the end of a test you can set a global success flag. This flag will be tested at the begining of each test. If the flag is not set by the end of one test(because it fails before finishing) all other tests will fail too.
Example:
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ConsecutiveFail{
private boolean success = true;
#Test
public void test1{
//fist two statements in all tests
assertTrue("other test failed first", success);
success = false;
//do your test
//...
//last statement
success = true;
}
#Test
public void test2{
//fist two statements in all tests
assertTrue("other test failed first", success);
success = false;
//do your test
//...
//last statement
success = true;
}
}
I was able to achieve what you are looking with intellij idea IDE, I am using community edition.
Go to Edit Configuration in the class where test methods available.( Run --> Edit Configurations)
Select Test kind as "Class"
as in the below Image.
When you run the Class Test it will execute all #Test Annotated methods inside the class as in below Picture.
If you need the consequence to be kept and failing a test not to fail the whole set, put all such tests in one and test by assume.
Here's example for TESTNG how to specify test running order:
#Test(priority = 1)
public void test1(){}
#Test(priority = 2)
public void test2(){}
#Test(priority = 3)
public void test3(){}