PowerMock.expectNew with andAnwser instead of andReturn - easymock

I'm trying to use PowerMock with andAnswer to return a test stub instead of the original class, but it doesn't seem to work. The test stub is a subclass of the original class.
expectNew(Foo.class, isA(String.class))).andAnswer(new IAnswer<Foo> {
#Override
public Foo answer() throws Throwable {
return new FooStub((String)getCurrentArguments()[0]);
}
}).anyTimes();
When the code tries to instantiate a new Foo, my answer method is never called and I get the following error:
java.lang.IllegalStateException: Must replay class Foo to get configured expectation.
Can anyone tell me what I'm doing wrong?

pass the invocation method argument and try the result calling invocation.getArugments[0]

Related

Selenium NUnit run from Main() or exe

I want to run all selenium tests from an exe. I tried the solution mentioned on this thread (Run NUnit test fixture programmatically)
This is what I have written
public class Runner{
public static int Main(string[] args)
{
return new AutoRun(Assembly.GetCallingAssembly())
.Execute(new String[]{"/test:Runner.Foo.Login" });}
[TestFixture]
public class Foo
{
IWebDriver driver;
[Test]
public void Initialize()
{
driver = new FirefoxDriver();// (#"C:\Selenium\Firefox");
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitWait =
TimeSpan.FromSeconds(10);
Console.WriteLine("Setup Browser");
}
[Test]
public void Login()
{
eWb.Classes.LoginUser.eWbLogin(driver, ConfigurationSettings.AppSettings["UserId"],
ConfigurationSettings.AppSettings["Password"], "CU");
}}}}
The Console opens and is not able to read the test method Login.
You are passing Assembly.GetCallingAssemby() as a constructor argument to AutoRun. Since this is in your Main, there is no calling assembly, so I assume the value passed is null. Being told to find tests in null, AutoRun is pretty much guaranteed not to find any.
The proper call is to pass no argument at all, since the tests are, in fact, in the assembly making the call. AutoRun itself will figure out what the calling assembly is and should find your tests.
The SO answer to which you list does not use GetCallingAssembly. It uses GetExecutingAssembly. However, since no argument works equally well, that's what I would use. In fact, with NUnit, you should generally use defaults first and only tailor arguments where it's necessary.
Suggest reading the documentation as well: https://github.com/nunit/docs/wiki

EasyMock 3.2: How to address public variables in a mocked class?

I'm trying to mock an open-source class. That class uses a number of public variables instead of get methods. I need to have the mocked class return another mocked class when that variable is accessed, but I'm not sure how. Here's an example:
SolrQueryRequest request = createNiceMock(SolrQueryRequest.class);
...
replay(request);
ResponseBuilder builder = createNiceMock(ResponseBuilder.class);
expect(builder.req).andReturn(request); // Throws exception
replay(builder);
The above example, however, throws the exception java.lang.IllegalStateException: no last call on a mock available on the builder.req line. Any idea how I can do this? Please note I don't have the option of refactoring the mocked classes.
Well, after playing around with it more I discovered it was pretty easy:
myBuilder.req = request;
Now when my class under test accesses the myBuilder.req variable, it is correctly set to my mocked SolrQueryRequest.

Easymock: Issue Mocking void DAO method - Unexpected method call

Found a workaround. See solution at the bottom
Ok I have been in EasyMock jail all day and I need some help getting out.
I have a void save() method I am mocking out.
public void save(PurchaseOrder po);
PurchaseOrder is an abstract class that has two children
USPurchaseOrder
CAPurchaseOrder
Here's my code in the JUnit test
MyDAO myDAO = createMock(MyDAO.class);
PurchaseOrder usPurchaseOrder = new USPurchaseOrder(msgUS);
myDAO.save(usPurchaseOrder);
expectLastCall().atLeastOnce();
PurchaseOrder caPurchaseOrder = new CAPurchaseOrder(msgCA);
myDAO.save(caPurchaseOrder);
expectLastCall().atLeastOnce();
replay(myDAO);
//execute code that uses DAO
I get the following error: Unexpected method call MyDAO.save(USPurchaseOrder#1a70b8):
The only problem here is that the DAO signature does not require a USPurchaseOrder, only a PurchaseOrder, which is what I am passing in.
Even doing this produces the same error
myDAO.save(new USPurchaseOrder(msgUS));
What am I doing wrong?
Workaround
Ok, I kept plugging away at this and while I don't understand why I am getting the error, I added the anyObject() to the code to get it to work.
MyDAO myDAO = createMock(MyDAO.class);
myDAO.save(anyObject(OrderRequest.class));
myDAO.save(anyObject(OrderRequest.class));
replay(myDAO);
//execute code that uses DAO
For matching method calls EasyMock uses equals() for method parameters. You should take it into account. So my guess is that you have not implemented equals() in your USPurchaseOrder and the default Object.equals() behavior is used, that compares whether the instances of USPurchaseOrder are the same, which are apparently not.

Mocking a final method with PowerMock + EasyMock

I'm trying to mock a call to the final method ResourceBundle.getString(). With PowerMock 1.4.12 and EasyMock 3.1, the call is not being mocked; instead, the "real" method is called.
My test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(ResourceBundle.class)
public class TestSuite {
#Before
public void setUp() throws Exception {
ResourceBundle resourceBundleMock = PowerMock.createNiceMock(ResourceBundle.class);
expect(resourceBundleMock.getString(BundleConstants.QUEUE)).andReturn("Queue");
PowerMock.replay(resourceBundleMock);
beanBeingTested.setMessages(resourceBundleMock);
}
...
}
Code in BeanBeingTested:
private ResourceBundle messages;
...
String label = messages.getString(BundleConstants.QUEUE);
Error message:
java.util.MissingResourceException: Can't find resource for bundle $java.util.ResourceBundle$$EnhancerByCGLIB$$e4a02557, key Queue
at java.util.ResourceBundle.getObject(ResourceBundle.java:384)
at java.util.ResourceBundle.getString(ResourceBundle.java:344)
at com.yoyodyne.BeanBeingTested.setUpMenus(BeanBeingTested.java:87)
When I step through the test case, the debugger shows the type of beanBeingTested.messages as "EasyMock for class java.util.ResourceBundle", so the mock is injected correctly. (Also, there's no error on the call to getString() within the expect() call during set up).
With a plain mock instead of a nice mock, I get the following error:
java.lang.AssertionError:
Unexpected method call handleGetObject("Queue"):
getString("Queue"): expected: 1, actual: 0
Any idea what I'm doing wrong?
Thanks.
You are creating an instance using EasyMock. Instead, when working with static methods, you must mock the class (using PowerMock).
It should work like that (tested with EasyMock 3.0 and PowerMock 1.5, though):
#RunWith(PowerMockRunner.class)
#PrepareForTest(ResourceBundle.class)
public class TestSuite {
#Before
public void setUp() throws Exception {
// mock the class for one method only
PowerMock.mockStaticNice(ResourceBundle.class, "getString");
// define mock-behaviour on the class, when calling the static method
expect(ResourceBundle.getString(BundleConstants.QUEUE)).andReturn("Queue");
// start the engine
PowerMock.replayAll();
}
}
(I'm aware this question is a few months old, but it might help others, though)
Try using:
#PrepareForTest({ResourceBundle.class, BeanBeingTested.class})
With only ResourceBundle in the PrepareForTest the mock will work when called directly from your unit test method, but when called from BeanBeingTested you get the real method being used.
Powermock documentation is lacking in this area.
Why bother mocking the call to the resource bundle? Generally, I try to avoid mocking the nuts and bolts of java, such as ArrayList, Date, etc. Resource bundles (and MessageFormat.format()) more or less fall into the same category for me. They generally operate on strings which are fundamentals, and if these things are broken or changing their behavior enough to break a test it's definitely something I want to know :)
Just let them grab the string (which presumably is about to be set in the UI, perhaps after . Don't bother to assert the value returned since you don't want edits to the bundle to break your test. If the string gets set on a mock UI component, This is a good place for anyObject(String.class) which correctly expresses the fact you (probably) don't actually care about the specific string displayed.
I also consider it a benefit when the test fails due to a missing message key. THAT I want to know.

Android Unit Tests Requiring Context

I am writing my first Android database backend and I'm struggling to unit test the creation of my database.
Currently the problem I am encountering is obtaining a valid Context object to pass to my implementation of SQLiteOpenHelper. Is there a way to get a Context object in a class extending TestCase? The solution I have thought of is to instantiate an Activity in the setup method of my TestCase and then assigning the Context of that Activity to a field variable which my test methods can access...but it seems like there should be an easier way.
You can use InstrumentationRegistry methods to get a Context:
InstrumentationRegistry.getTargetContext() - provides the application Context of the target application.
InstrumentationRegistry.getContext() - provides the Context of this Instrumentation’s package.
For AndroidX use InstrumentationRegistry.getInstrumentation().getTargetContext() or InstrumentationRegistry.getInstrumentation().getContext().
New API for AndroidX:
ApplicationProvider.getApplicationContext()
You might try switching to AndroidTestCase. From looking at the docs, it seems like it should be able to provide you with a valid Context to pass to SQLiteOpenHelper.
Edit:
Keep in mind that you probably have to have your tests setup in an "Android Test Project" in Eclipse, since the tests will try to execute on the emulator (or real device).
Your test is not a Unit test!!!
When you need
Context
Read or Write on storage
Access Network
Or change any config to test your function
You are not writing a unit test.
You need to write your test in androidTest package
Using the AndroidTestCase:getContext() method only gives a stub Context in my experience. For my tests, I'm using an empty activity in my main app and getting the Context via that. Am also extending the test suite class with the ActivityInstrumentationTestCase2 class. Seems to work for me.
public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity>
EmptyActivity activity;
Context mContext = null;
...
#Before
public void setUp() {
activity = getActivity();
mContext = activity;
}
... //tests to follow
}
What does everyone else do?
You can derive from MockContext and return for example a MockResources on getResources(), a valid ContentResolver on getContentResolver(), etc. That allows, with some pain, some unit tests.
The alternative is to run for example Robolectric which simulates a whole Android OS. Those would be for system tests: It's a lot slower to run.
You should use ApplicationTestCase or ServiceTestCase.
Extending AndroidTestCase and calling AndroidTestCase:getContext() has worked fine for me to get Context for and use it with an SQLiteDatabase.
The only niggle is that the database it creates and/or uses will be the same as the one used by the production application so you will probably want to use a different filename for both
eg.
public static final String NOTES_DB = "notestore.db";
public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db";
First Create Test Class under (androidTest).
Now use following code:
public class YourDBTest extends InstrumentationTestCase {
private DBContracts.DatabaseHelper db;
private RenamingDelegatingContext context;
#Override
public void setUp() throws Exception {
super.setUp();
context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
db = new DBContracts.DatabaseHelper(context);
}
#Override
public void tearDown() throws Exception {
db.close();
super.tearDown();
}
#Test
public void test1() throws Exception {
// here is your context
context = context;
}}
Initialize context like this in your Test File
private val context = mock(Context::class.java)

Resources