I would like to run a specific JUnit test method programmatically. I know I can run the whole test using the following code snippet:
Class<?> test = Class.forName("MyTestClass");
JUnitCore junit = new JUnitCore();
Result result = junit.run(test);
However, I would like to run a specific method within this test class which contains multiple methods.
It would also be fantastic if I could control the setUp/tearDown behaviour.
Thank you
There's an overloaded JUnitCore#run method version that accepts Request. While Request has Request#method factory method to:
Create a Request that, when processed, will run a single test. This is
done by filtering out all other tests. This method is used to support
rerunning single tests.
If you need to control #setUp / #tearDown (i.e., methods marked with #Before and/or #After annotations) you can extend the class and override methods you need to alter.
Related
I have a unit test class where my unit under test is dependent on another class. The dependency is mocked using Mockito and then setup with a generic stub that's run before every unit test, using JUnit's #BeforeEach annotation. See the below pseudo-code.
#ExtendWith(MockitoExtension.class)
public class FooFactoryTest {
#Mock
private BarDependency barDependency;
#InjectMocks
private FooFactory unitUnderTest;
#BeforeEach
public void setup() {
when(barDependency.leftBar(any())).thenReturn(new Bar());
when(barDependency.rightBar(any())).thenReturn(new Bar());
}
... many tests ...
This setup works perfectly for 9 of my 10 unit tests. Unfortunately one of my tests is failing with the following error:
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at nl.devillers.mockito.FooFactoryTest.setup(FooFactoryTest.java:69)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
Now, I understand the error and why it's thrown, because in that specific test my unit under test short-circuits early and doesn't hit all the stubs that have been setup. I'm aware there's a lenient option in Mockito, but that'll disable the check for the entire class/project.
My question is: how do I disable this strictness for one specific unit test?
Again: I do not want to disable the strictness at the class or project level, since I think it's valuable check. I also do not want to move my setup code to the tests that do need the stubs, because then I have to duplicate the setup code nine times. In this case I just want to disable or skip the check for this specific test.
You can avoid this check at the test-level by resetting the mock with the stub that's not being called. This is a bit of a work around, but it'll allow you to pass your test without having to make the mock lenient for your entire test class or removing the mock entirely from your setup method.
To reset your barDependency mock, add the following line of code to the end of your test that is failing with a UnnecessaryStubbingException.
Mockito.reset(barDependency);
If none of the stubs on barDependency are being used, you can also place this line at the beginning of your test with your other arrangements, which is a little cleaner. Or alternately, put it at the top of your test method and then setup the stubs you do need. This essentially overrides whatever is being setup in your generic setup method.
You can also use lenient in the code of your #BeforeEach, like this:
#BeforeEach
public void setup() {
lenient().when(barDependency.leftBar(any())).thenReturn(new Bar());
lenient().when(barDependency.rightBar(any())).thenReturn(new Bar());
}
This should not be necessary, based on this doc in the UnnecessaryStubbingException:
Mockito JUnit Runner triggers UnnecessaryStubbingException only when none of the test methods use the stubbings. This means that it is ok to put default stubbing in a 'setup' method or in test class constructor. That default stubbing needs to be used at least once by one of the test methods.
I have a test method as below that two other test methods are dependent to this method and this method should run before these two each time and not only once for both.
#Test(dataProvider = "requestParameterProvider", groups = "jsonRequest")
public void saveNewActivity_correctValues(Service service,
Map<String, Object> requestMap){}
#Test(dependsOnMethods = "saveNewActivity_trackRequest_correctValues", dataProvider = "responseParameterProvider")
public void commitActivity_correctValues(Service service){}
#Test(dependsOnMethods = "saveNewActivity_trackRequest_correctValues", dataProvider = "exceptionParameterProvider")
public void failActivity_correctValues(Service service, FailureReason failureReason){}
what happens at above case is saveNewActivity_correctValues method run once first and then two other method run after that. but i want first method to be invoked two times before each dependent method and once as separate test. i can't put first method as #BeforeMethod because it is already a test and have a provider of it's own.
Use the #Before annotation on the method you want to run before all tests.
If you don't want it to run before all methods, but only some, either refactor your tests out into 2 classes and use #Before in one, and not in the other and move your methods appropriately.
The other option is to just call the method(s) from each test you want them to run before.
I'm assuming you are using JUnit - so see here:
http://junit.sourceforge.net/javadoc/org/junit/Before.html
If not, update your post with what you are using.
I want to test some database-related classes in my application using TestNG framework.
To make it easier I added a test group "database" and made a test class TestUtil, which contains two methods: one with #BeforeGroups(groups = "database") annotation, it's setting up EntityManager and some other resources, and another one marked with #AfterGroups(groups = "database"), which frees up these resources.
Most of my test classes persisting some entities to database during the test, and I want to clean up the DB after all test methods of the class are invoked.
If I use #AfterClass annotation, it runs after the #AfterGroups methods, what is unacceptable for me because clean-up method still needs active EntityManager and other DB-related resources.
I can mark those clean-up methods with #Test(dependsOnMethods = "lastTestMethodInThisClass"), but in this case I'll need to edit this annotation each time I add new test method to the class.
Is there another, more convenient way to do this job?
No, there is no such annotation which allows you to run code after all #Test and before #AfterGroups. But instead of #Test(dependsOnMethods = "lastTestMethodInThisClass") you can implement org.testng.IMethodInterceptor as listener and change #Test order in org.testng.IMethodInterceptor#intercept - basically search your 'last test' in the list put your 'last test' which handles/closes resources to the end and return modified list. So you don't have to change dependsOnMethods when you add new test because interceptor do it for you.
If you want to run a cleanup method after all the tests are invoked, you can write your code in your cleanup method with #AfterSuite annotation. This will be executed after the whole suite has finished execution.
I have a junit test testArchive(). The Junit test tests the archive() method that archives a file and returns the url to it as a String. The URL is defined as an instance variable inside the Junit Test class.
class Prepare {
private String url = "";
#Test
public void testArchive() {
String url = getService().archive();
}
#Test
public void testSendEmail() {
getService().sendEmail(url) // Url is turning out to be null
}
} // end of class
I am writing another Junit test for sendEmail() which emails the URL. But the URL is turning out to be null, though its defined as a class variable
Can you please let me know how I need to correct my Junit test for send email?
Thank you
Short answer:
You should really not do that.
Detailed answer:
Unit tests (and therefore JUnit tests as well) are intended to run separately and independently from each other. Each test should check only one method, regardless of result of another method or another test. So in your case, method testSendEmail() should use some hard coded URL, or better few different URLs.
Keep in mind that:
Test cases should not have side effects: the .archive() looks like will produce side effects
Test cases should not assume an execution order of other test cases: your testSendEmail seems to assume testArchive is executed first, which is wrong
Test cases should not depend on external factors: the getService calls looks like an external (uncontrolled) factor
Test cases should be independent and self-contained
Instead of one test cases depending on the outcome of another,
you could use a private helper method that both test cases can call.
I removed the 2nd JUnit test and consolidated the tests into 1. Both archive and email will happen in one test.
I'm driving a suite of Selenium tests (actually WebDriver-backed Selenium) using JUnit 4.8.2. I'd like the tests to automatically take a screenshot of the browser as soon as the test fails an assertion. All the tests inherit from SeleniumBaseTestCase, and the majority then further inherit from from SeleniumBastTestCaseWithCompany (which uses #Before and #After methods to create and then clean up common test data via Selenium).
I've tried adding a subclass of TestWatchman as a #Rule in SeleniumBaseTestCase, overriding TestWatchman's failed method to take the screenshot. The trouble is that the #After methods cleaning up the test data are being run before TestWatchman's failed method is called, so the screenshots are all of the final step of the clean-up, not the test that failed.
Looking into it a little, it seems that TestWatchman's apply method just calls the passed Statement's evaluate method (the only exposed method), which calls the #After methods, leaving TestWatchman (or any other Rule) no chance to insert any code between the execution of the test and of the #After methods, as far as I can tell.
I've also seen approaches that create a custom Runner to alter the Statements created so that methods annotated with the custom #AfterFailure are run before #After methods (so the screenshot can be taken in such an #AfterFailure method), but this relies on overriding BlockJUnit4ClassRunner's withAfters method, which is deprecated and due to become private, according to the documentation, which suggests using Rules instead.
I've found another answer on SO about the #Rule lifecycle that makes it sound like this simply might not be possible in JUnit 4.8, but may be possible in JUnit 4.10. If that's correct then fair enough, I'd just like confirmation of that first.
Any thoughts on an elegant and future-proof way in which I can achieve what I want would be much appreciated!
You are right in your analysis, #Befores and #Afters are added to the list of Statements before any Rules. The #Before gets executed after the #Rule and the #After gets executed before the #Rule. How you fix this depends on how flexible you can be with SeleniumBaseTestCaseWithCompany.
The easiest way would be to remove your #Before/#After methods and replace them with an ExternalResource. This could look something like:
public class BeforeAfterTest {
#Rule public TestRule rule = new ExternalResource() {
protected void before() throws Throwable { System.out.println("externalResource before"); }
protected void after() { System.out.println("externalResource after"); }
};
#Test public void testHere() { System.out.println("testHere"); }
}
this gives:
externalResource before
testHere
externalResource after
This field can be put into your base class, so it gets inherited/overridden. Your problem with ordering between #After and your rules then goes away, because you can order your rules how you like, using #RuleChain (in 4.10, not 4.8).
If you can't change SeleniumBaseTestCaseWithCompany, then you can extend BlockJUnit4ClassRunner, but don't override withAfters, but override BlockJUnit4ClassRunner#methodBlock(). You can then call super.methodBlock, and reorder the Statements as necessary[*].
[*]You could just copy the code, and reorder the lines, but withRules is private and therefore not callable from a subclass.