I am writing test codes with Selenium, TestNG. I am trying to set some elements on the #BeforeClass section as I am repeating those actions on the same page. But I am getting null pointer exception. Is there a way to fix this issue?
public class RunTest {
private static WebElement user;
private static WebElement pass;
private static WebElement login;
#BeforeClass
public static void driveraBaglan() {
//Driver is declared here. I removed it to give the simple code.
user = driver.findElement(By.id("user"));
pass = driver.findElement(By.id("pass"));
login = driver.findElement(By.xpath("//button[contains(.,'Log In')]"));
statusMessage = driver.findElement(By.id("login-status-message")).getText();
}
#Test(priority=1)
public void loginNoInfo() {
user.clear();
pass.clear();
}
I get the null pointer error on user.clear() , pass.clear() and login.click() functions. All tests on the page runs on the same page. I don't want to use repeated "find element by id" tags on each test on the page.
#BeforeTest: The annotated method will be run before any test method belonging to the classes inside the <test> tag is run.
#BeforeClass: The annotated method will be run before the first test method in the current class is invoked
try to change the annotation
#BeforeTest
public static void driveraBaglan() {
//Driver is declared here. I removed it to give the simple code.
user = driver.findElement(By.id("user"));
pass = driver.findElement(By.id("pass"));
login = driver.findElement(By.xpath("//button[contains(.,'Log In')]"));
statusMessage = driver.findElement(By.id("login-status-message")).getText();
}
I never used TestNG but I do use Junit. Trying to replicate your example, I obtained the following exception:
[TestNG] Running:
/Users/davide.patti/Library/Caches/IntelliJIdea2017.3/temp-testng-customsuite.xml
java.lang.NullPointerException
at TestSO.loginNoInfo(TestSO.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1123)
at org.testng.TestNG.run(TestNG.java:1031)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
The reason was because, in my imported classes I was using the BeforeClass of Junit:
import org.junit.BeforeClass;
import org.testng.annotations.Test;
and not of TestNG.
If your null pointer exception is the same, be sure that your imported classes are the correct ones:
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
I got this same issue by an accidental change I've done.
You may also get the null pointer exception on objects you are initializing in #BeforeClass or #BeforeTest, when you have a dilemma situation as below (where the class is set to as a disabled test class while having enabled test methods).
#Test(enabled=false)
public class TestClass{
A a;
#BeforeClass
public void doBeforeClass(){
a=new A();
//
}
#Test
public void test1(){
a.callMethod1();
}
#Test
public void test2(){
a.callMethod2();
}
}
Here, when you are running full-suite by putting #Test(enabled=false) only for the class, still the suite will run individual tests in the class since #Test annotations are present there. However, since #BeforeClass is not running for whole class, object 'a' is not initialized and will cause null pointer exceptions.
In such cases, the individual #Test annotations too need to be changed to #Test(enabled=false)
Related
I'm working to unit test my Java app..
My goal is to use Powermock to create a spy on an instance of the BOProcessor class. BOProcessor has a final void method; I will setup my spy to throw an exception when this method is called. I will also be mocking MyDao in this same test, but mocking this class is straightforward. The mocked MyDao will then be passed into an instance of MyDaoService named classUnderTest. I will then make assertions against classUnderTest.
Whenever I try to setup the above scenario, Powermock (or Mockito?) throws an InvalidUseOfMatchersException when I setup the doThrow on my spy. Strangely, this exception is only thrown when the doThrow expectation is followed by a call to classUnderTest. If I remove the later call the classUnderTest, the expectation works fine. Even weirder - classUnderTest doesn't even use the spy that is throwing the error!
This is the entirety of my test code outlined above. To highlight the problem, I've removed all code not directly related. (I've even removed the whole purpose of this test.)
package my.package;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
import org.junit.Test;
public class WhatAmIDoingWrong {
#Test
public void whatAmIDoingWrong() {
MyDao mockedDao = mock(MyDao.class);
BOProcessor processor = new BOProcessor();
BOProcessor mockedProcessor = spy(processor);
MyDaoService classUnderTest = new MyDaoService(mockedDao);
doThrow(new Exception()).when(mockedProcessor).process(any(FakeBusinessObject.class));
classUnderTest.interactWithDao();
}
}
Here is the exception - thrown (ironically) from the doThrow line of my test code - which I'm trying to solve.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at my.package.WhatAmIDoingWrong.whatAmIDoingWrong(WhatAmIDoingWrong.java:21)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
at my.package.MyDaoService.interactWithDao(MyDaoService.java:33)
at my.package.WhatAmIDoingWrong.whatAmIDoingWrong(WhatAmIDoingWrong.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
Here are the classes used by my test. To reiterate, the MyDaoService named classUnderTest doesn't even know about the spy of BOProcessor; it only works against the mock of MyDao. But the expectations on the BOProcessor spy only fail if the classUnderTest is called.
public class BOProcessor {
public final void process(FakeBusinessObject bar) {}
}
public class FakeBusinessObject {
}
import java.util.Collections;
import java.util.List;
public class MyDao {
public MyDao() {}
public List<String> getAllData(){
return Collections.emptyList();
}
}
public class MyDaoService {
private MyDao applicationDao;
public MyDaoService(MyDao applicationDao) {
this.applicationDao = applicationDao;
}
public synchronized void interactWithDao() {
applicationDao.getAllData();
}
}
I'm usin JUnit 4.12, Mockito 1.10.19, and Powermock 1.7.4. The project is running Spring 4.3.12RELEASE with spring-test included.
Why is Powermock throwing this exception? Am I not using the any Matcher correctly? Why on earth is this exception only thrown when a later call interacts with a different mock?
Thanks for the help!
It turns out that I was using Spies wrong. Something in the way org.mockito.stubbing.Stubber.when(T mock) is implemented means I cannot set expectations on the Spy the way I wanted to. But a Capture was actually a better fit for my use case anyway.
In the end, my test looked like this:
public class FixedNow{
#Test
public void fixedNow() {
MyDao mockedDao = mock(MyDao.class);
BOProcessor mockedProcessor = mock(BOProcessor.class);
FakeBusinessObject problematicBO = new FakeBusinessObject();
ArgumentCaptor<FakeBusinessObject> fakeBOCaptor = ArgumentCaptor.forClass(FakeBusinessObject.class);
MyDaoService classUnderTest = new MyDaoService(mockedDao, mockedProcessor);
doThrow(new Exception()).when(mockedProcessor).process(eq(problematicBO));
doNothing().when(mockedProcessor).process(fakeBOCaptor.capture());
classUnderTest.interactWithDao();
assertThings(BOCaptor.getValue());
}
}
Thanks for your thoughts!
I am using TestNg frame work to execute citrus frame work test cases. In the below code I am unable to get citrus text context object getting an error while executing the test case
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import com.consol.citrus.annotations.CitrusResource;
import com.consol.citrus.annotations.CitrusXmlTest;
import com.consol.citrus.context.TestContext;
import com.consol.citrus.dsl.testng.TestNGCitrusTestRunner;
public class GenricTest extends TestNGCitrusTestRunner {
static
{
System.setProperty("citrus.spring.application.context", "file:G:\\Citrus\\citrus-context.xml");
}
#Test #Parameters("context")
#CitrusXmlTest(packageScan = "file:C:\\xitrus")
public void CitrusTest(#Optional #CitrusResource TestContext context)
{
}
}
while executing above code to get citrus text context object i am getting the follwing error
[Utils] [ERROR] [Error] org.testng.TestNGException:
Unsupported type parameter : class com.consol.citrus.context.TestContext
at org.testng.internal.Parameters.convertType(Parameters.java:318)
at org.testng.internal.Parameters.createParameters(Parameters.java:203)
at org.testng.internal.Parameters.createParameters(Parameters.java:443)
at org.testng.internal.Parameters.handleParameters(Parameters.java:569)
at org.testng.internal.Invoker.handleParameters(Invoker.java:1308)
at org.testng.internal.Invoker.createParameters(Invoker.java:1036)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1126)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
at org.testng.TestRunner.privateRun(TestRunner.java:744)
at org.testng.TestRunner.run(TestRunner.java:602)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:380)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:375)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
at org.testng.SuiteRunner.run(SuiteRunner.java:289)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1301)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1226)
at org.testng.TestNG.runSuites(TestNG.java:1144)
at org.testng.TestNG.run(TestNG.java:1115)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
I don't know what you've configured in your Citrus context so I'll be posting a complete example.
Citrus tests are run with TestNG but Citrus itself is a Spring application. That means you can configure Beans inside a configuration class as you would in a Spring app and then you can use #Autowired to access the beans in your tests.
Here is an example configuration class where I've configured the beans that I need for testing:
#Import({})// you can import more configuration classes here
public class CitrusConfiguration {
#Value("${inbound.service.url}")
private String serviceUrl;
#Value("${external.api.mock.port}")
private int externalApiMockPort;
#Bean
public HttpClient inboundClient() {
return CitrusEndpoints.http()
.client()
.requestUrl("http://" + serviceUrl)
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.build();
}
#Bean
public HttpServer externalApiMock() {
return CitrusEndpoints.http()
.server()
.port(externalApiMockPort)
.autoStart(true)
.timeout(10000)
.build();
}
}
After this we need to tell Citrus which class is the main configuration class inside a property file like this: src/test/resources/citrus-application.properties
citrus.spring.java.config=<your.package>.CitrusConfiguration
And now we can write a test like this:
#Test
public class InboundApiControllerIT extends TestNGCitrusTestRunner {
#Autowired
private HttpClient httpClient;
#CitrusTest
public void okTest() {
http(action -> action.client(httpClient)
.send()
.post("/inbound")
.payload("{" +
"\"userName\": \"Bruce.Wayne\"," +
"\"operation\": \"call-a-pizza\"" +
"}"));
http(action -> action.client(httpClient)
.receive()
.response(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.payload("{" +
"\"success\": true" +
"}"));
}
}
Please don't use a static block to configure Citrus (or anything in general) and use a setup like the one described above. If the documentation cannot help you, you can always check the samples here.
The Citrus test components are pretty flexible inside the tests, so you should not need to change any of their configuration values dynamically. I also don't recommend doing this. If you need to change anything inside a test component (like an HttpClient) that cannot be explicitly configured inside a test action, then I recommend you create a new component with that special configuration.
I am new to Spring unit Testing. Writing test cases for the Spring rest Controller. When I am writing the test cases in this way
#WebAppConfiguration
#ContextConfiguration(locations = {"file:src/test/resources/applicationContext.xml"})
public class TaskControllerIntegrationTest extends AbstractTransactionalTestNGSpringContextTests {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#BeforeClass
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void testGetAllTasks() throws Exception {
mockMvc.perform(get("/v1/testSessions/{testSessionId}/tasks", 1l))
.andExpect(status().isOk());
}
}
I am getting the testcase failed don't know why :( while If i initialize the MockMvc using the standalone controller it works perfect and my allTest cases are passes.The setup for the MockMvc using standalone controller is in this way. It's for unit testing:
#Mock
private TaskService taskServiceMock;
#InjectMocks
private TaskController taskController;
private MockMvc mockMvc;
#Spy
List<Task> allTasks = new ArrayList<Task>();
/* #Spy
List<TaskSessionModel> taskSessionModelList = new ArrayList<TaskSessionModel>();*/
#BeforeClass
public void setUp() {
// Mockito.reset(taskServiceMock);
MockitoAnnotations.initMocks(this);
// taskSessionModelList = getAllTaskSessionModels();
allTasks = getAllTasks();
this.mockMvc = MockMvcBuilders.standaloneSetup(taskController).build();
}
#Test
public void testGetAllTasks() throws Exception {
// when(taskSessionDao.findAllByTestSession(1l)).thenReturn(taskSessionModelList);
when(taskServiceMock.getAllTasks(1l)).thenReturn(allTasks);
mockMvc.perform(get("/v1/testSessions/{testSessionId}/tasks", 1l)
.accept(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].name", is("Average")));
List<Task> expTaskList = taskController.getAllTasks(1l);
verify(taskServiceMock, times(2)).getAllTasks(1l);
verifyNoMoreInteractions(taskServiceMock);
assertEquals(allTasks, expTaskList);
}
But if i write the same unit test by using the WebApplicationContext .. I will get error and test cases will failed :
java.lang.AssertionError: Status
Expected :200
Actual :500
<Click to see difference>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:654)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:152)
at com.blueoptima.dt.controller.TaskControllerIntegrationTest.testGetAllTasks(TaskControllerIntegrationTest.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:200)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:212)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:707)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:74)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
I don't know what's the wrong? I tried almost all the solution for the WebApplicationContext setup(see the first code) it's in the same way as I see .. on this website and mostly configuration in spring official website and other after googling it but still error remains same?
Have a look into this ! Cheers !!
Go back one step, forget about all Spring and technology stuff and ask yourself what you want to achieve with the tests?
If you want to do a real integration tests, don't mock controllers or services, so the following code makes no sense:
#Mock
private TaskService taskServiceMock;
That should be the problem in your setup. Remove all mocks instead of MockMvc and try again. Take a cup of coffee and read the official documentation, it will teach you all the details including setting up a in-memory-database and setting up the Spring TestContext Framework.
To access your controllers, you have two choices, depending on how deep the tests shall go.
I'm working with a large test suite for an old Java codebase. Long story short, it uses DBUnit to upload static read-only datasets from the local harddisk. At present this is being done on the per-test level, which means the suite takes a ridiculously long time to run.
I'm trying to make a shared static class to be shared at the suite-level. (We also didn't have a proper test suite defined -- I made one using ClasspathSuite)
Another wrinkle is that all of are tests are using #RunWith(PowerMockRunner.class) -- so there's occasionally classpath issues mucking up what I think would normally solve things.
Here's a simple case of what's not working.
Java Code Under Test
Static Dependency in Codebase
package com.somecorp.proj;
public class SomeDependency {
public static String getStaticString() {
// some resource intensive process we don't want running in unit tests
return "real value";
}
}
Class Under Test 1
package com.somecorp.proj;
public class UnderTest {
public String getIt() {
return "Here is the value: " + SomeDependency.getStaticString();
}
}
Class Under Test 2
package com.somecorp.proj;
public class AlsoUnderTest {
public String getTheThing() {
return "some other value using it: " + SomeDependency.getStaticString();
}
}
JUnit Code
Code with init method I want run only ONCE at the start of the suite run
package com.somecorp.proj.testClasses;
public class StaticTestClassRequiringInitialization {
private static String testString;
public static void init() {
// Some expensive stuff
System.out.println("EXPENSIVE INITIALIZATION");
testString = "a test string";
}
public static String getTestString() {
return testString;
}
}
Test 1
package com.somecorp.proj;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.somecorp.proj.testClasses.StaticTestClassRequiringInitialization;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeDependency.class)
public class TestUnderTest {
#Before
public void setUp() {
PowerMockito.mockStatic(SomeDependency.class);
PowerMockito.when(SomeDependency.getStaticString()).
thenReturn(StaticTestClassRequiringInitialization.getTestString());
}
#Test
public void testGetIt() {
UnderTest ut = new UnderTest();
assertEquals(
"Here is the value: a test string",
ut.getIt()
);
}
}
Test 2
package com.somecorp.proj;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.somecorp.proj.testClasses.StaticTestClassRequiringInitialization;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeDependency.class)
public class TestAlsoUnderTest {
#Before
public void setUp() {
PowerMockito.mockStatic(SomeDependency.class);
PowerMockito.when(SomeDependency.getStaticString()).
thenReturn(StaticTestClassRequiringInitialization.getTestString());
}
#Test
public void testGetTheThing() {
AlsoUnderTest ut = new AlsoUnderTest();
assertEquals(
"some other value using it: a test string",
ut.getTheThing()
);
}
}
Test Suite
package com.somecorp.proj;
import static org.junit.extensions.cpsuite.SuiteType.RUN_WITH_CLASSES;
import static org.junit.extensions.cpsuite.SuiteType.TEST_CLASSES;
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.BeforeSuite;
import org.junit.extensions.cpsuite.ClasspathSuite.ClassnameFilters;
import org.junit.extensions.cpsuite.ClasspathSuite.SuiteTypes;
import org.junit.runner.RunWith;
import com.somecorp.proj.testClasses.StaticTestClassRequiringInitialization;
#RunWith(ClasspathSuite.class)
#SuiteTypes({RUN_WITH_CLASSES, TEST_CLASSES})
#ClassnameFilters({".*Test.*"})
public class ProjectJUnitSuite {
#BeforeSuite
public static void setUpBeforeSuite() {
StaticTestClassRequiringInitialization.init();
}
}
JAR details
powermock-mockito-1.4.12-full.jar
mockito-all-1.9.0.jar
cpsuite-1.2.6.jar
javassist-3.16.1-GA.jar
Using Junit 4.8.1
And the trace of the test failure (notably not an error - a failure) (for one test...2nd one is pretty much identical):
org.junit.ComparisonFailure: expected:<...her value using it: [a test string]> but was:<...her value using it: [null]>
at org.junit.Assert.assertEquals(Assert.java:123)
at org.junit.Assert.assertEquals(Assert.java:145)
at com.somecorp.proj.TestAlsoUnderTest.testGetTheThing(TestAlsoUnderTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:102)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:42)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.extensions.cpsuite.ClasspathSuite.run(ClasspathSuite.java:196)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
How might I get this shared static initializer to run once per suite and be referenceable from all of my Powermock-enabled unit tests?
I got the initialization to occur only once by using the #PowerMockIgnore annotation on all the test classes referencingStaticTestClassRequiringInitialization.
In this case in particular adding the below annotation to both of the JUnit test classes would do the trick.
#PowerMockIgnore("com.somecorp.proj.testClasses.StaticTestClassRequiringInitialization")
I had tried this before, and it had not initially worked because the arguments I had initially passed had been either:
Too broad - Classes that needed to be mocked were no longer being loaded by powermock classloader because I passed an entire package to PowerMockIgnore
Not broad enough - A few dependencies more complex than the example above were present requiring me to ignore some other classes. The result were some strange class loading mismatch errors.
This won't work in all cases, (in particular it won't work if the StaticTestClassRequiringInitialization uses classes that are also being mocked in the test), but it does work in this case.
I had also done some investigation into the PowerMockAgent to avoid the PowerMockRunner, and therefore many of the associated Classloading issues altogether, but the production code under test* required suppressing static initalizers, so it was a non-starter.
*Apologies for not sharing the full source, such are the perils of asking questions for large proprietary codebases.
I am trying to run a quick selenium example to get started, and am having trouble. I have written JUnit test cases before and they work fine, but here's my code and error.
package alltests;
import testsuites.SeleniumTestTutorial;
import junit.framework.Test;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for SeleniumTutorial");
suite.addTestSuite(SeleniumTestTutorial.class);
return suite;
}
}
Here's an old tutorial I am using. I didn't write these tests, they will most likely fail, I'm just trying to get them to run.
package testsuites;
import junit.framework.TestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;
public class SeleniumTestTutorial extends TestCase{
private static Selenium browser;
#BeforeClass
public static void init() {
browser = new DefaultSelenium("localhost", 4444, "*firefox",
"http://new.music.yahoo.com/");
browser.start();
}
#Test
public void isVideosHpLoaded() {
browser.open("http://new.music.yahoo.com/");
browser.click("//*[#id=\"YMusic_HeaderNavItemMenu2\"]/a/span");
browser.waitForPageToLoad("5000");
System.out.println("checking title " + browser.getTitle());
assertEquals("Music Videos on Yahoo! Music", browser.getTitle());
}
#Test
public void isTop100VideosModuleLoaded() {
Number numElements = browser
.getXpathCount("//*[#id=\"ymMvHpTopVideos\"]/div/div/h2/a");
String modHeaderText = browser
.getText("//*[#id=\"ymMvHpTopVideos\"]/div/div/h2/a");
assertEquals(1, numElements.intValue());
assertEquals("Top 100 Videos", modHeaderText);
}
#Test
public void isVideoStationsModuleLoaded() {
Number numElements = browser
.getXpathCount("//*[#id=\"ymMvHpVideoStationsContentContainer\"]/div/div[2]/h2/a");
String modHeaderText = browser
.getText("//*[#id=\"ymMvHpVideoStationsContentContainer\"]/div/div[2]/h2/a");
assertEquals(1, numElements.intValue());
assertEquals("Video Stations", modHeaderText);
}
#Test
public void countTotalVideoRecs() {
Number numElements = browser
.getXpathCount("//*[#id=\"ymusicRecommendHp\"]//ul[#class=\"ymusic_thumbnailList\"]/li");
assertEquals(6, numElements.intValue());
}
#AfterClass
public static void cleanup() {
browser.stop();
}
}
Here's the error I am getting. I've used this format for other JUnit tests, and I have never had any problems. I also can't seem to find an updated tutorial for using JUnit and Selenium. If anyone has any good links I would not be opposed. Thanks in advance!
junit.framework.AssertionFailedError: No tests found in testsuites.SeleniumTestTutorial
at junit.framework.Assert.fail(Assert.java:47)
at junit.framework.TestSuite$1.runTest(TestSuite.java:97)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
I think it's because you're mixing JUnit 3 and JUnit 4 style tests.
If you're using JUnit 3.x, you want to extend TestCase, as you have, but then you need all your test methods to be named "testXYZ" (i.e. starting with the word test). The #Test annotations are ignored.
For JUnit 4, you don't extend TestCase, and you use the annotations.
You are mixing a JUnit 3 Test Suite and JUnit 4 test classes. You need to create a JUnit 4 test suite:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
#RunWith(Suite.class)
#Suite.SuiteClasses({
SeleniumTestTutorial.class
})
public class AllTests {
}
When you execute a TestSuite (JUnit 3), it searches for methods which start with 'test'. For a JUnit 4 suite (with #RunWith(Suite.class)), then it searches for methods with the #Test annotation.