I have a unit test I am writing for a class, and this class uses a ConfigurationManager I wrote to get configuration from a TOML object (and therefore from a TOML file).
The Code
Here is the relevant ConfigurationManager code:
public class ConfigurationManager {
// DEFAULT_LOGGING_LEVEL should represent level to use in production environment.
private final static Level DEFAULT_LOGGING_LEVEL = Level.FINE;
private final static String LOG_LEVEL_ENV_PROPERTY = "LOG_LEVEL";
private final static String TOML_FILE_NAME = "config.toml";
private final static String LOCAL_ENV_PROPERTY = "local";
private final static String ENV_PROPERTY = "MY_ENV";
private static Logger CM_LOGGER;
private Environment environment;
public ConfigurationManager() {
environment = new Environment();
CM_LOGGER = new LoggerUtil(ConfigurationManager.class.getName(), getLoggingLevel()).getLogger();
}
public File getTomlFile() throws URISyntaxException, FileNotFoundException {
URI uri = getConfigURI();
File tomlFile = new File(uri);
if (!tomlFile.exists()) {
String err = TOML_FILE_NAME + " does not exist!";
CM_LOGGER.severe(err);
throw new FileNotFoundException(err);
}
return tomlFile;
}
/**
* #return A URI representing the path to the config
* #throws URISyntaxException if getConfigURI encounters bad URI syntax.
*/
private URI getConfigURI() throws URISyntaxException {
return getClass().getClassLoader().getResource(TOML_FILE_NAME).toURI();
}
/**
* Method for getting the app configuration as a toml object.
*
* #return A toml object built from the config.toml file.
* #throws URISyntaxException if getConfigURI encounters bad URI syntax.
* #throws FileNotFoundException if getTomlFile can't find the config.toml file.
*/
public Toml getConfigToml() throws URISyntaxException, FileNotFoundException {
return new Toml().read(getTomlFile());
}
}
And here is the code that calls this Configuration Manager:
public class Listener {
// Initializations
private static final String CONFIG_LISTENER_THREADS = "listenerThreads";
private static final String DEFAULT_LISTENER_THREADS = "1";
/**
* Constructor for getting app properties and initializing executor service with thread pool based on app prop.
*/
#PostConstruct
void init() throws FileNotFoundException, URISyntaxException {
ConfigurationManager configurationManager = new ConfigurationManager();
int listenerThreads = Integer.parseInt(configurationManager.getConfigToml()
.getString(CONFIG_LISTENER_THREADS, DEFAULT_LISTENER_THREADS));
this.executorService = Executors.newFixedThreadPool(listenerThreads);
LOGGER.config("Listener executorService threads: " + listenerThreads);
}
...
}
And here is the test for that code (See comment to see where NPE is triggered):
public class ListenerTests {
#Mock
ConfigurationManager mockCM;
#InjectMocks
Listener listener = new Listener();
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
#Test
public void testListener_ShouldInit() throws FileNotFoundException, URISyntaxException {
when(mockCM.getConfigToml().getString(any(), any())).thenReturn("5"); // !!!NPE TRIGGERED BY THIS LINE!!!
listener.init();
verify(mockCM, times(1)).getConfigToml().getString(any(), any());
}
}
The Problem
I get a NullPointerException as follows
java.lang.NullPointerException
at com.bose.source_account_listener.ListenerTests.testListener_ShouldInit(ListenerTests.java:37)
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.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.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
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.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I have a guess as to the problem here but I'm not sure how to validate my guess. My guess is that I am mocking the ConfigurationManager, but the mock doesn't know that the ConfigurationManager can generate a TOML file which has a getString method, so I end up getting the NPE. This makes me think that I need a mock TOML for my mock ConfigurationManager, but I am neither certain this is the case or that this is the proper solution.
I am new to Mockito and Java in general so any help would be appreciated.
You need to mock every bit of your call, not just the full call. mockCM.getConfigToml() has no mock response, so it returns null, and a toString is invoked on a null object. Your options are to return a non-mocked "Toml" or mock a Toml and then set that up with a when configuration.
Toml tomlMock = Mockito.mock(Toml.class);
when(mockCM.getConfigToml()).thenReturn(tmolMock);
when(tmolMock.getString(any(), any())).thenReturn("5");
You're trying to mock the method of what is returned by calling getConfigToml. That is, you need to mock the object of what should be returned by getConfigToml, and then call getString on that object.
Related
In a simple test class like the one below:
#SpringBootTest
#Slf4j
#ActiveProfiles("test")
public class LocalizerTest {
#Autowired
AddressInfoLocalizer addressInfoLocalizer;
#Test
public void localizeIp() {
String ip = "8.8.8.8";
Optional<CityResponse> response = addressInfoLocalizer.localize(ip);
response.ifPresent(cityResponse -> log.info("{}", cityResponse));
}
}
With the AddressInfoLocalizer (sorry for the strange name but I had to make it up) being basically like this:
#Slf4j
#Component
public class AddressInfoLocalizer {
#Value("${geolocalization.dbpath}")
private String databasePath;
private DatabaseReader database;
#PostConstruct
public void initialize() {
log.info("GeoIP2 database path:{}", databasePath);
File database = new File(databasePath);
try {
this.database = new DatabaseReader.Builder(database).build();
} catch (IOException ioe) {
this.database = null;
log.warn("Problems encountered while initializing IP localization database, skipping resolutions");
}
}
public Optional<CityResponse> localize(String ipAddressString) {
if (isNull(database)) {
log.warn("Attempted to resolve an IP location with database problems, skipping.");
return Optional.empty();
}
try {
InetAddress ipAddress = InetAddress.getByName(ipAddressString);
return ofNullable(database.city(ipAddress));
} catch (UnknownHostException uhe) {
log.error("Unknown host {}, {}", ipAddressString, uhe.getCause());
return Optional.empty();
} catch (IOException ioe) {
log.error("IO error while opening database, {}", ioe.getCause().toString());
return Optional.empty();
} catch (GeoIp2Exception gip2e) {
log.error("GeoIP error, {}", gip2e.getCause().toString());
return Optional.empty();
}
}
}
I keep getting a NullPointerException when calling (in the test) addressInfoLocalizer.localize(ip);,
java.lang.NullPointerException
at com.bok.parent.LocalizerTest.localizeIp(LocalizerTest.java:26)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
while debugging I can actually see that the addressInfoLocalizer object is null.
I've created other classes the same way, but only this one seems to have that problem, what could be wrong?
What I found out is that not always the #SpringBootTest is enough, in some classes/cases (to be honest I don't have a 100% clear idea so I'm not gonna say stupidities) it is needed that you manually choose the test-runner, like below:
#SpringBootTest
#RunWith(SpringRunner.class)
public class FooTest {
...
}
Keep in mind that if you decide to instantiate a dependency by yourself then Spring won't be able to inject all the needed classes, and then you'd need to change the runner into something like #RunWith(MockitoJUnitRunner.class)
(credits to JUNIT Autowired instance is always null)
A better approach is to use spring's underlying mock beans.
#SpringBootTest(classes= AddressInfoLocalizer.class)
this is actually the new recommended way.
Two things here:
If you're testing, the ideal way is to mock instead of autowire(there can be exceptions)
You should use #ExtendWith(MockitoExtension.class) or #RunWith(MockitoJUnitRunner.class) so that your components will be loaded in spring context. However ExtendWith is preferred way to initialize beans/components. Because the later(RunWith) loads the entire spring context which might take more time
So, your code should look something like:
#Slf4j
#ActiveProfiles("test")
#ExtendWith(MockitoExtension.class)
public class LocalizerTest {
#Mock
AddressInfoLocalizer addressInfoLocalizer;
#Test
public void localizeIp() {
String ip = "8.8.8.8";
//Mock here.
Optional<CityResponse> response = addressInfoLocalizer.localize(ip);
response.ifPresent(cityResponse -> log.info("{}", cityResponse));
}
}
Reference/Read more:
https://www.baeldung.com/mockito-junit-5-extension
https://stackoverflow.com/questions/55276555/when-to-use-runwith-and-when-extendwith
https://www.javadoc.io/static/org.mockito/mockito-junit-jupiter/3.10.0/org/mockito/junit/jupiter/MockitoExtension.html
I create a Java project for training with Selenium and JUnit. A first test connect the user to the website, the second test check an information in the homepage when the user is connected. I don't understand why my second test begin and stop with a NullPointerException...
I use this files :
A main files => for declare a JunitCore and run two class test (via jCore.run(test1.class, test2.class)
main :
public class Main {
public static void main(String[] args){
JUnitCore jCore = new JUnitCore();
//jCore.addListener(new ExecutionListener());
jCore.run(WebsiteLoginTest.class, WebsiteCheckEventTest.class);
}
}
Two tests class files :
test1.java :
public class Test1 {
#Test
public void testlogin(){
WebsiteHomePage homePage = new WebsiteHomePage().open();
homePage.login(...);
}
}
test2.java :
public class WebsiteCheckEventTest {
#Test
public void websiteCheckEvent(){
System.out.println("a");
WebsiteHomePageConnected homePageConnected = new WebsiteHomePageConnected();
System.out.println("b");
homePageConnected.checkEvent();
System.out.println("c");
}
}
And two "page" files : (use page object pattern)
WebsiteHomePage (no logged) :
public class WebsiteHomePage extends WebsitePage<WebsiteHomePage> {
#FindBy(id = "usernameLogin") WebElement usernameInputText;
#FindBy(id = "passwordLogin") WebElement passwordInputText;
#FindBy(id = "loginSubmit") WebElement loginInputSubmit;
#Override
public ExpectedCondition getPageLoadCondition() {
return ExpectedConditions.titleContains("Homepage");
}
#Override
public String getPageUrl() {
return "";
}
public void login(String univers, String login, String password){
usernameInputText.sendKeys(login);
passwordInputText.sendKeys(password);
loginInputSubmit.click();
}
public WebsiteHomePage open() {
return new WebsiteHomePage().openPage(WebsiteHomePage.class);
}
}
WebsiteHomePageConnected (when the user is connected via the first test) :
public class WebsiteHomePageConnected extends WebsitePage<WebsiteHomePageConnected> {
#FindBy(id = "playerName") WebElement playerNameLi;
#FindBy(id = "eventContent") WebElement eventContentDiv;
#FindBy(id = "eventListWrap") WebElement eventListDiv;
#Override
public ExpectedCondition getPageLoadCondition() {
return ExpectedConditions.visibilityOf(playerNameLi);
}
#Override
public String getPageUrl() {
return "";
}
public void checkEvent(String event){
System.out.println("111"); // is displayed in the console
eventContentDiv.click();
System.out.println("222"); // isn't displayed in the console
}
}
When I run the program, the console shows :
a
b
c
111
...but no 222, the program stop in the WebsiteHomePageConnected file in the line with "eventContentDiv.click()" without any error message.
In the main file, if I uncomment //jCore.addListener(new ExecutionListener()) the console show :
a
b
c
111
Execution of test case failed : java.lang.NullPointerException
at page.WebsiteHomePageConnected.checkEvent(WebsiteHomePageConnected.java:34)
at test.WebsiteCheckEventTest.websiteCheckEvent(WebsiteCheckEventTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
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.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
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.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.runner.JUnitCore.run(JUnitCore.java:105)
at org.junit.runner.JUnitCore.run(JUnitCore.java:94)
at Main.main(Main.java:32)
So, the "eventContentDiv" seems be the problem, but when I check manually the website, after connection, I find the div with the id "eventContent" (via firebug ctrl+f). Manually, More precisely :
I go to the homepage website
I enter log and password, I submit
Im redirected to the homepage connected (the url is a little different)
I open firebug, press ctrl+f, search "eventContent" and I find the element
So...why my program doesn't find this element ?
~UPDATE~
This is the abstract websitePage Class :
public abstract class WebsitePage<T>{
private static final String BASE_URL = "http://www.test.com/";
public T openPage(Class<T> pageObject){
T page = PageFactory.initElements(getDriver(), pageObject);
getDriver().get(BASE_URL + getPageUrl());
ExpectedCondition pageLoadCondition = ((WebsitePage) page).getPageLoadCondition();
WaitForPageToLoad(pageLoadCondition);
return page;
}
private static final int LOAD_TIMEOUT = 30;
private static final int REFRESH_RATE = 2;
private void WaitForPageToLoad(ExpectedCondition pageLoadCondition) {
Wait wait = new FluentWait(getDriver())
.withTimeout(LOAD_TIMEOUT, TimeUnit.SECONDS)
.pollingEvery(REFRESH_RATE, TimeUnit.SECONDS);
}
public abstract ExpectedCondition getPageLoadCondition();
public abstract String getPageUrl();
}
~UPDATE 2~
Ive made a mistake in my com in the public class WebsiteHomePageConnected. Change :
...
System.out.println("222"); // is displayed in the console
...
to
...
System.out.println("222"); // isn't displayed in the console
...
I´m developing an Eclipse 4 RCP Application and I want to test some functions of my Parts.
I have a Test Class like this:
#BeforeClass
public static void initUI() {
display = new Display();
shell = new Shell(display);
configPart = new ConfigPart();
configPart.postConstruct(shell);
}
#Test
public void testConfigPart() {
String testText = "TitleText";
configPart.title.setText(testText);
assertEquals(testText, ConfigHandler.getInstance().getInternalConfig()
.getTitle());
}
During the creation of the ConfigPart a DataBinding is created and that is where I run into an AssertionFailedException. The statement is:
DataBindingContext ctx = new DataBindingContext();
Is there a way to avoid this or is there another way to test E4 Applications?
Edit:
The statement(s) where the Exception is raised:
public DataBindingContext(Realm validationRealm) {
Assert.isNotNull(validationRealm, "Validation realm cannot be null");
public static void isNotNull(Object object, String message) {
if (object == null) throw new AssertionFailedException("null argument:" + message);
The Stack Trace:
org.eclipse.core.runtime.AssertionFailedException: null argument:Validation realm cannot be null
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:85)
at org.eclipse.core.databinding.DataBindingContext.<init>(DataBindingContext.java:95)
at org.eclipse.core.databinding.DataBindingContext.<init>(DataBindingContext.java:82)
at de.uni_due.s3.jack.editor.parts.config.ConfigPart.addDataBinding(ConfigPart.java:350)
at de.uni_due.s3.jack.editor.parts.config.ConfigPart.postConstruct(ConfigPart.java:81)
at de.uni_due.s3.jack.editor.parts.config.ConfigPartTest.initUI(ConfigPartTest.java:28)
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:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
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:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
A call to the empty constructor new DataBindingContext() delegates to this(Realm.getDefault()) (see Eclipse source code). This means that you need to have some kind of a stub Realm set as default for your testing purposes.
You can use this solution from the Eclipse Wiki. Here is a copy-paste from the Wiki (adapted for your setup). I would think about whether you really need to have the setup in #BeforeClass or if #Before would be better.
public class DefaultRealm extends Realm {
private Realm previousRealm;
public DefaultRealm() {
previousRealm = super.setDefault(this);
}
/**
* #return always returns true
*/
public boolean isCurrent() {
return true;
}
protected void syncExec(Runnable runnable) {
runnable.run();
}
/**
* #throws UnsupportedOperationException
*/
public void asyncExec(Runnable runnable) {
throw new UnsupportedOperationException("asyncExec is unsupported");
}
/**
* Removes the realm from being the current and sets the previous realm to the default.
*/
public void dispose() {
if (getDefault() == this) {
setDefault(previousRealm);
}
}
}
Test code:
private static DefaultRealm realm;
#BeforeClass
public static void initUI() {
display = new Display();
shell = new Shell(display);
realm = new DefaultRealm();
configPart = new ConfigPart();
configPart.postConstruct(shell);
}
#AfterClass
public static void tearDownUI() {
realm.dispose();
}
I have the following code
public class A{
public void createFile() {
File tempXmlFile = null;
String extension = ".xml";
String name = "someName";
try {
tempXmlFile = File.createTempFile(name, extension);
if (tempXmlFile.exists()) {
tempXmlFile.delete();
}
} catch (IOException e) {
System.out.println(e.getStackTrace());
}
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class testA extends TestCase{
private A classUnderTest;
#Override
#Before
public void setUp() {
classUnderTest = PowerMock.createMock(A.class); //the class is more complex in my case and I have to mock it
}
public void testCreateFile() throws IOException{
String extension = ".xml";
String name = "someName";
PowerMock.mockStatic(File.class);
File tempFileMock = PowerMock.createMock(File.class);
expect(File.createTempFile(name, extension)).andReturn(tempFileMock);
expect(tempFileMock.exists()).andReturn(true);
expect(tempFileMock.delete()).andReturn(true);
replay(File.class, tempFileMock, classUnderTest);
classUnderTest.createFile();
verify(File.class, tempFileMock, classUnderTest);
}
}
In the test class as I said the class under test must be mocked(I can't create a new object).
When I run the test I get:
java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:174)
at org.easymock.EasyMock.expect(EasyMock.java:156)
at myPackage.testA.testCreateFile(testA.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:163)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:113)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:111)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:87)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:44)
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)
I read the documentation here http://code.google.com/p/powermock/wiki/MockSystem but the test stil wont't work. Am I missing something?
Edit: I tested the previous code with a real A object (and removed it from replay)
classUnderTest = new A();
but I still get the same exception.
Try adding File.class to #PrepareForTest.
try the org.powermock.reflect.internal.WhiteboxImpl.newInstance() method to create the object of the class and then call method directly.
1) this will suppress the constructor of the class
2) if your class contains static block then use suppressStaticInitilaizationFor to suppress that.
regards
Anil Sharma
Add File.class to #PrepareForTest and check the imports of replay and verify. They should be from PowerMock.
I think you need to suppress constructor
Check this
http://code.google.com/p/powermock/wiki/SuppressUnwantedBehavior
I keep getting the following exception,
java.lang.IllegalStateException: No tx on thread at org.apache.geronimo.transaction.manager.TransactionManagerImpl.getActiveTransactionImpl(TransactionManagerImpl.java:201)
at org.apache.geronimo.transaction.manager.TransactionManagerImpl.getResource(TransactionManagerImpl.java:194)
at org.apache.openejb.core.transaction.JtaTransactionPolicy.getResource(JtaTransactionPolicy.java:111)
at org.apache.openejb.core.transaction.EjbTransactionUtil.afterInvoke(EjbTransactionUtil.java:76)
at org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:246)
at org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:178)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:260)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:240)
at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:91)
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:284)
at $Proxy70.call(Unknown Source)
at com.xyz.cms.epgmgmt.entitymanager.ProviderManagerTest.testWithTransaction(ProviderManagerTest.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:168)
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 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 am using OpenEJB4 for JUnit testing.
The EJB itself is stateless with no transaction annotation (which makes the Transaction required). I found an older post on this forum and tried the same fix but didnt work. I dont have hibernate validation on my classpath. Am using Hibernate 3.
My test is as follows,
public class ProviderManagerTest extends TestCase {
Context context;
/**
* Bootstrap the Embedded EJB Container
*
* #throws Exception
*/
protected void setUp() throws Exception {
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.core.LocalInitialContextFactory");
p.put("log4j.category.OpenEJB.options ", " debug");
p.put("RcsDB", "new://Resource?type=DataSource");
p.put("RcsDB.JdbcDriver", "oracle.jdbc.driver.OracleDriver");
p.put("RcsDB.JdbcUrl", "jdbc:oracle:thin:#dbserver:1521:ttv");
p.put("RcsDB.JtaManaged", "true");
p.put("RcsDB.JtaManaged", "true");
p.put("RcsDB.username", "username");
p.put("RcsDB.password", "password");
context = EJBContainer.createEJBContainer(p).getContext();
context.bind("inject", this);
}
#Test
public void testWithTransaction() throws Exception {
Caller transactionalCaller = (Caller) context.lookup("java:global/cms_epgmgmt/TransactionBean");
transactionalCaller.call(new Callable() {
public Object call() throws Exception {
Provider testProvider = new Provider();
testProvider.setName("test");
IProviderManager providerManager = null;
providerManager = (IProviderManager) context.lookup("java:global/cms_epgmgmt/ProviderManager");
providerManager.create(testProvider);
return null;
}
});
}
/*private void testProviderCreation()
{
Provider testProvider = new Provider();
testProvider.setName("test");
providerManager.create(testProvider);
}
*/
public static interface Caller {
public <V> V call(Callable<V> callable) throws Exception;
}
/**
* This little bit of magic allows our test code to execute in
* the scope of a container controlled transaction.
*/
#Stateless
#TransactionAttribute(REQUIRES_NEW)
public static class TransactionBean implements Caller {
public <V> V call(Callable<V> callable) throws Exception {
return callable.call();
}
}
}
where provider manager is as below,
#Local(IProviderManager.class)
#Stateless
public class ProviderManager implements IProviderManager{
#PersistenceContext(unitName = "epgmanagerjpaunit")
private EntityManager entityManager;
public void create(Provider provider)
{
entityManager.persist(provider);
}
}
Thanks in advance,
-v-