Accessing spring context in testng's #BeforeTest - java

I would like to register some web scopes to the spring context in my #BeforeTest method. But it turns out that spring context is still null at that point.
The test runs fine though, if I change into #BeforeMethod. I wonder how I can access the context in #BeforeTest, because I don't want the scope registration code to be repeated for each test methods.
Below are my code snippets.
public class MyTest extends MyBaseTest {
#Test public void someTest() { /*...*/ }
}
#ContextConfiguration(locations="/my-context.xml")
public class MyBaseTest extends AbstractTestNGSpringContextTests {
#BeforeTest public void registerWebScopes() {
ConfigurableBeanFactory factory = (ConfigurableBeanFactory)
this.applicationContext.getAutowireCapableBeanFactory();
factory.registerScope("session", new SessionScope());
factory.registerScope("request", new RequestScope());
}
/* some protected methods here */
}
Here's the error message when running the test:
FAILED CONFIGURATION: #BeforeTest registerWebScopes
java.lang.NullPointerException
at my.MyBaseTest.registerWebScopes(MyBaseTest.java:22)

Call springTestContextPrepareTestInstance() in your BeforeTest method.

TestNG runs #BeforeTest methods before #BeforeClass methods. The springTestContextPrepareTestInstance() is annotated with #BeforeClass and sets up the applicationContext. This is why the applicationContext is still null in a #BeforeTest method. #BeforeTest is for wapping a tagged group of tests. (It does not run before each #Test method, so it's a bit of a misnomer).
Instead of using #BeforeTest, you should probably use #BeforeClass (which is run once, before the first #Test in the current class). Be sure it depends on springTestContextPrepareTestInstance method, as in
#BeforeClass(dependsOnMethods = "springTestContextPrepareTestInstance")
public void registerWebScopes() {
ConfigurableBeanFactory factory = (ConfigurableBeanFactory)
this.applicationContext.getAutowireCapableBeanFactory();
factory.registerScope("session", new SessionScope());
factory.registerScope("request", new RequestScope());
}
The #BeforeMethod works, too (as you mentioned) because they run after #BeforeClass methods.

Related

Why doesn't my #BeforeClass method run when executing a subclass test method?

I'm using IntelliJ IDEA CE 2018.3 and JUnit 4.12.
I have a test class that looks like this:
#RunWith(HierarchicalContextRunner.class)
public class TestClass {
#BeforeClass
public static void beforeAll() {
//start a server for all tests to hit
}
#Before
public void before() {
//init a common request object for each test
}
#Test
public void itShouldHaveSomeCommonProperty() {
//check some common thing
}
public class SomeSubTestClass {
#Before
public void before() {
//do some test case-specific setup
}
public class SomeOtherSubTestClass {
#Test
public void itShouldDoSomething() {
//hit the service and assert something about the result
}
}
}
}
When I tell IntelliJ to run the class, everything works as expected. However, if I want to just run the itShouldDoSomething test (which I'm doing by setting up a run configuration that targets the SomeOtherSubTestClass class), the beforeAll method is not executed. Both of the before methods are executed in the correct order, but not the static beforeAll method.
Am I misunderstanding something, or is this a bug?
It is not a bug.
The beforeAll method is static and therefore tied to the class and not the instance. This is why it is not executed when calling tests in inner classes or sub-classes.
To ensure it being called you would have to define a #BeforeClass method in each of your inner classes which then call the method on the outer class.

How to run #BeforeClass method before each #Test

When I run my #Tests manualy, one by one - everything is fine. But when I run them all together - I`ve got an error. So how can I run #BeforeClass before each #Test. I cant use #Before becorse in my #BeforeClass I do some work in testing class constructor.
Testing class constructor:
public HttpUtils() {
this.httpClient = HttpClients.createDefault();
}
Before class:
#BeforeClass
public static void init() throws IOException {
mockStatic(HttpClients.class);
final CloseableHttpClient closeableHttpClient = createMock(CloseableHttpClient.class);
when(HttpClients.createDefault()).thenReturn(closeableHttpClient);
}
If I run all test. On second test Ive got HttpClient not like mock, but like real object, and lately have error coz of it.
Use #Before instead of #BeforeClass to execute before every test
#Before
public static void init() throws IOException {
with #Before causes that method to be run before the Test method. The #Before methods of superclasses will be run before those of the current class.
If you want to execute any method before each test class you should go for #Before annotation. By using #BeforeClass annotation you only call that method once in the test class.

How to use #BeforeClass and #AfterClass within a JerseyTest suite

It turns out that JUnit wants #BeforeClass and #AfterClass to be static and this doesn't get along well with JerseyTest's configure method override. Is there a known way to configure the Jersey application while still being able to access JUnit's utility methods?
public class MyControllerTest extends JerseyTest {
#BeforeClass
public static void setup() throws Exception {
target("myRoute").request().post(Entity.json("{}"));
}
#Override
protected Application configure() {
return new AppConfiguration();
}
}
Hence beforeClass needs to be static, target cannot be called because of its instance-method nature. While trying to use the constructor instead, it turns out that configure is run after the constructor and this prevents the setup-request to be executed and will therefor fail naturally.
Any advice is more than appreciated, thanks!
What we did in several cases to avoid heavy setups in such situations is to use a boolean flag to run that setup conditionally.
public class MyControllerTest extends JerseyTest {
private static myRouteSetupDone = false;
#Before
public void setup() throws Exception {
if (!myRouteSetupDone) {
target("myRoute").request().post(Entity.json("{}"));
myRouteSetupDone = true;
}
}
#Override
protected Application configure() {
return new AppConfiguration();
}
}
#Before does not require the static modifier and will be executed before every test-method.

TestNG: constant NPE on #AfterMethod

I have randomly failing tests no my CI server.
The problem that I'm getting NullPointerException's within tearDown() method.
The common structure which causes this behavior is simple:
#Test
class MyRandomlyFailingTest extends AbstractTestNGSpringContextTests {
#Autowired
private SomeSpringBean someSpringBean;
#BeforeMethod
public void beforeMethod() {
someSpringBean.addTestData("");
}
#AfterMethod
public void afterMethod() {
someSpringBean.removeTestData("");
}
}
So I have randomly null fields in #AfterMethod which were obviously fine when running tests. But somehow it happens that fields are null again.
#Autowired is provided by spring 3.2
So I can't find the reason why it happens. Only solution to this is to stop using #AfterMethod annotations at all

TestNg's #BeforeTest on base class only happening once per fixture

I'm trying to use #BeforeTest to get code to ... run once before every test.
This is my code:
public class TestBase {
#BeforeTest
public void before() {
System.out.println("BeforeTest");
}
}
public class TestClass extends TestBase{
#Test
public void test1(){}
#Test
public void test2(){}
}
"BeforeTest" is only printed once, not twice. What am I doing wrong?
Use #BeforeMethod, not #BeforeTest.
The meaning of #BeforeTest is explained in the documentation.
"BeforeTest" is only printed once, not twice. What am I doing wrong?
***Sorry. I haven't noticed that you is written #BeforeTest , but in your example #BeforeTest almost equals #BeforeClass , and better to use #BeforeClass , when you haven't anymore test classes.
#BeforeClass" should be declared in same class that your tests methods, not differently!
//Example
package test;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class Tests {
private String bClass;
private String bMethod1;
private String bMethod2;
#BeforeClass
public void beforeClass() {
bClass = "BeforeClass was executed once for this class";
}
#BeforeMethod
public void beforeMetodTest1() {
bMethod1 = "It's before method for test1";
}
#Test
public void test1() {
System.out.println(bClass);
System.out.println(bMethod1);
}
#BeforeMethod
public void beforeMethodTest2() {
bMethod2 = "It's before method for test2";
}
#Test
public void test2() {
System.out.println(bClass);
System.out.println(bMethod2);
}
}
#BeforeClass will executed once, before your all tests methods in this class. #BeforeMethod will executed before test method, before which it is written.
#BeforeClass may be only one in test class, in difference #BeforeMethod!(If it is some #BeforeClass, they are carried out by turns, but it not a correct composition of the test)
P.S. Sorry for my English :)
According to documentation, a method annotated with #BeforeTest is run before any #Test method belonging to the classes inside the tag is run.
From my experience:
Each #BeforeTest method is run only once
If you have several #BeforeTest methods, the order of their execution depends on the order of the class containing those #BeforeTest method.
You could test this by setting up a simple example.
If you use #beforeTest, that method will be run once in the beginning of every <test> (we specify in the test suit xml file) if that test contains that class
All the #befortests within all the classes within a <test> will be executed at the beggining of that test
Official Documentations are so unclear and mostly ambiguous. This is why many don't like to read it. Not to mention no real-life examples shown.
If you are trying to get code to run once before every test, then you are looking for #BeforeMethod, not #BeforeTest. Because each of your tests independently considered methods.
#BeforeMethod runs before each method. I see you have two methods with the names test1() and test2(). Expect BeforeMethod to run before each of them.
#BeforeTest runs only once before ALL of your tests (test-methods). In Selenium, WebDriver is called once, this is better practice for testing.
#BeforeMethod will invoke WebDriver before each test, this is not good practice, especially when you have regression tests with hundreds of them to run.
For example, if you run this code (these are separate classes, not inner to each other, only showing for demonstration purposes here):
public class TestClass extends Base {
#Test
public void test1() {
System.out.println("Running Test 1");
}
#Test
public void test2() {
System.out.println("Running Test 2");
}
}
public class Base {
#BeforeTest
public void beforeTest() {
System.out.println("Before Test");
}
#AfterTest
public void afterTest() {
System.out.println("After Test");
}
#BeforeMethod
public void beforeMethod() {
System.out.println("Before Method");
}
#AfterMethod
public void afterMethod() {
System.out.println("After Method");
}
}
And you will get this as an output:
Before Test
Before Method
Running Test 1
After Method
Before Method
Running Test 2
After Method
After Test
As you can see BeforeMethods run before each test while BeforeTest and AfterTest run only once before and after completing ALL tests.
Hope this clarified the difference for you.

Categories

Resources