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.
Related
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.
I am writing a unit test for an existing legacy code base. It contains some classes that I would like to mock, which have static initializer at the class level.
When I try to mock the class it will fail, during the mock creation with an exception from code within the static initialization that does not work in the JUnit test environment (depends on certain app server).
this is a simple illustration of my scenario
Class to mock:
public class StaticClass {
static {
doSomething();
}
private static void doSomething() {
throw new RuntimeException("Doesn't work in JUnit test environment");
}
public StaticClass(){
}
}
The Unit test framework is leveraging PowerMock/EasyMock/JUnit 4 on Java 7.
This is what I was trying to do in my unit test
#RunWith(PowerMockRunner.class)
#PrepareForTest({StaticClass.class})
public class SampleTest {
#Test
public void test() {
PowerMock.mockStatic(StaticClass.class);
PowerMock.replay(StaticClass.class);
StaticClass mockInstance = EasyMock.createNiceMock(StaticClass.class);
EasyMock.replay(mockInstance);
System.out.println(mockInstance.toString());
}
}
This throws the java.lang.ExceptionInInitializerError exception at the line: PowerMock.mockStatic(StaticClass.class);
Other than refactoring the StaticClass in my example, is there any other way to use PowerMock to mock the static initializer, or methods called from it to do nothing?
I found the solution thanks to question Why PowerMock is attempting to load the server.xml file if the static class is mocked out?
Use the PowerMock #SuppressStaticInitializationFor annotation. See their documentation for it here PowerMock wiki - Suppress Unwanted Behavior
This test code now works:
#RunWith(PowerMockRunner.class)
#SuppressStaticInitializationFor("com.my.test.StaticClass")
public class SampleTest {
#Test
public void test() {
StaticClass mockInstance = EasyMock.createNiceMock(StaticClass.class);
EasyMock.replay(mockInstance);
System.out.println(mockInstance.toString());
}
}
I have two test classes, MyFirstTest and MySecondTest. Running each independently works fine. When I run both (in eclipse select the test folder which contains these files, right click, run as junit), MySecondTest fails because MyClass is still mocked when it runs its' tests. MyFirstTest requires MyClass to be mocked. MySecondTest requires MyClass to not be mocked. I thought the tearDownMocks was suppose to 'demock' the classes.
public class MyFirstTest {
#Before
public void setUp() throws Exception {
Mockit.setUpMocks(MockMyClass.class);
}
#After
public void tearDown() throws Exception {
Mockit.tearDownMocks(MockMyClass.class);
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
Mockit.tearDownMocks(MockMyClass.class);
}
#MockClass(realClass = MyClass.class, stubs = "<clinit>")
public static class MockMyClass {
...
public class MySecondTest {
The right way to do it is like mentioned below: Mock the class and assign it to a variable. And then, using that variable, you can destroy or clear the mock so that it doesn't impact any other test case.
MockUp<PmRequestData> mockpmreq = new MockUp<PmRequestData>() {
#Mock
public Map<String, KPIData> getKpiDataMap() {
return datamap;
}
};
mockpmreq.tearDown();
The Mockit.tearDownMocks() method accepts real classes and not the mocks. So, the right code would be:
Mockit.tearDownMocks(MyClass.class);
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.
Is it possible to run an external command before running tests in a given JUnit file? I run my tests using the Eclipse's Run command. Using JUnit 4.
Thanks.
Very vague question. Specifically, you didn't mention how you are running your JUnit tests. Also you mentioned 'file', and a file can contain several JUnit tests. Do you want to run the external command before each of those tests, or before any of them are executed?
But more on topic:
If you are using JUnit 4 or greater then you can tag a method with the #Before annotation and the method will be executed before each of your tagged #Test methods. Alternatively, tagging a static void method with #BeforeClass will cause it to be run before any of the #Test methods in the class are run.
public class MyTestClass {
#BeforeClass
public static void calledBeforeAnyTestIsRun() {
// Do something
}
#Before
public void calledBeforeEachTest() {
// Do something
}
#Test
public void testAccountCRUD() throws Exception {
}
}
If you are using a version of JUnit earlier than 4, then you can override the setUp() and setUpBeforeClass() methods as replacements for #Before and #BeforeClass.
public class MyTestClass extends TestCase {
public static void setUpBeforeClass() {
// Do something
}
public void setUp() {
// Do something
}
public void testAccountCRUD() throws Exception {
}
}
Assuming you are using JUnit 4.0, you could do the following:
#Test
public void shouldDoStuff(){
Process p = Runtime.getRuntime().exec("application agrument");
// Run the rest of the unit test...
}
If you want to run the external command for every unit test, then you should do it in the #Before setup method.