JMockit: how to set properties on injectable? - java

Consider the following code:
#Tested
CodeToTest codeToTest;
#Injectable
Injected injected;
#Test
public void test() {
new Expectations() {{ ... }}
assertThat(codeToTest.memberVariable).isEqualTo("x");
}
//
public class CodeToTest { public CodeToTest(Injected injected) { memberVariable = injected.getProperty("x") } }
I want to test CodeToTest. CodeToTest needs Injected to be injected into it's constructor. How do I set a property such as injected.setProperty("x") so that it is available for access in CodeToTest?

The test at hand should be covering a specific method of CodeToTest; the constructor should have its own tests like your test does. So for example, if the constructor is setting a field according to what gets passed in, like this:
public class Bar {
public int getValue() {
return 8675309;
}
}
public class Foo {
public String field = null;
public Foo(Bar b) {
this.field = "" + b.getValue();
}
public String getField() {
return this.field;
}
public char getFirstChar() {
return getField().charAt(0);
}
}
Here I am setting a String field according to an int found in a Bar that was passed into the constructor. I wish to unit test my getFirstChar() method ...
#Tested Foo foo;
#Injectable Bar bar;
#Test
public void test() throws Exception {
// ...
}
Now, as you point out, in this case my field has already been set before test() even starts. So I have two choices here: Firstly, since I am pulling out the field based on its getter, I can partially mock my class being tested:
#Test
public void test() throws Exception {
new Expectations(foo) {{
foo.getField(); result = "24601";
}};
char c = foo.getFirstChar();
assertThat(c, is('2'));
}
OR, if you don't want to do this or if you are doing direct field access rather than via getter, you can use Deencapsulation (part of JMockit) to set the internal field and then test:
#Test
public void test() throws Exception {
Deencapsulation.setField(foo, "field", "24601");
char c = foo.getFirstChar();
assertThat(c, is('2'));
}
And of course, I test my constructor separately:
#Test
public void testConstructor() throws Exception {
new Expectations() {{
bar.getValue(); result = 24601;
}};
Foo foo2 = new Foo(bar);
String fieldValue = foo2.getField(); // or use Deencapsulation
assertThat(fieldValue, is("24601"));
}
Hope this helps, and good luck!

Related

How can I fix this behavior of getMethod()?

In class A, i got a function called updateAttribute. In class B, I got a junit test, which stores during execution this function in a Method object (code is simplified).
public class A {
public Optional<AttributeObject> updateAttribute(
#ApiParam("Qual of attribute") #PathParam("qual") #Qual final String qual,
#NotNull #Valid final UpdateObject a) {
// here, I've cut a few lines of code
return null;
}
}
public class ATest extends AnotherTest {
#Test
public void someTest()
throws NoSuchMethodException, SecurityException {
try (
// some code I've cut
final Method method =
A.getClass().getMethod("updateAttribute", String.class, UpdateObject.class);
// some code I've cut
}
}
}
The junit test fails at this call of .getMethod() with:
java.lang.IllegalArgumentException: HV000181: Wrong number of
parameters. Method or constructor
java.util.Optional"<"packageName.A">"#updateAttribute(String,
UpdateObject) expects 1 parameters, but got 2.
(...)
When I change the call to
final Method method =
A.getClass().getMethod("updateAttribute", String.class);
or similar, the trace just claims - as expected - that this method doesn't exist.Any ideas how to fix this?
Not an answer, just content that doesn't fit into a comment.
Reduced the code to this:
#Test
public void someTest()
throws NoSuchMethodException, SecurityException {
final Method method =
A.class.getMethod("updateAttribute", String.class, Integer.class);
}
}
class A {
public Optional<String> updateAttribute(
final String qual, Integer a) {
return null;
}
}
And that works fine.
Not reproducable.

Mocking chained methods calls using PowerMock

I have a class which I would like to test with a public static method that contains some chained method calls. Assuming that an exception occurs during the chained method calls, how do I handle this effectively and make it return some specific value?
Following is the code sample of the test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class,CodeWithYetAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = PowerMockito.spy(new CodeWithYetAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithYetAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithYetAnotherPrivateMethod);
CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);
PowerMockito.doReturn(true).when(codeWithYetAnotherPrivateMethod, "getGambling");
//PowerMockito.doReturn(codeWithYetAnotherPrivateMethod).when(codeWithAnotherPrivateMethod, "getGambleValue");
PowerMockito.spy(CodeWithPrivateMethod.class);
CodeWithPrivateMethod.startGamble();
}
}
Following is the code sample for the class under test
public class CodeWithPrivateMethod {
public static void startGamble() {
Boolean gamble = CodeWithAnotherPrivateMethod.getGambleValue()
.getGambling();
if (gamble) {
System.out.println("kaboom");
}else{
System.out.println("boom boom");
}
}
}
Following is the code sample for the class that gets called from the class under test
public class CodeWithAnotherPrivateMethod {
static CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = new CodeWithYetAnotherPrivateMethod();
public static CodeWithYetAnotherPrivateMethod getGambleValue() {
return codeWithYetAnotherPrivateMethod; //works fine
return null; // fails
}
}
Following is the code sample for the other class that gets called from the class under test
public class CodeWithYetAnotherPrivateMethod {
public Boolean getGambling() {
return false;
}
}
So Assuming I return a null value from getGambleValue() method of CodeWithAnotherPrivateMethod class, how do I handle this null value effectively in my testclass?
This is how to specify expected exceptions using Mockito:
#Test(expected = NullPointerException.class)
public void when_gambling_is_true_then_always_explode() throws Exception {
...
Before I found out about this I would do:
#Test
public void when_gambling_is_true_then_always_explode() throws Exception {
// setup omitted
try {
CodeWithPrivateMethod.startGamble();
}
catch(NullPointerException e) {
// expected
return;
}
fail("Expected NullPointerException");
}
EDIT: Testing multiple classes that call each other statically like this is a severe code smell. Unit tests should test a single class and inline static calls should be limited to utility classes.
Another comment: your example class names are very confusing. Next time please stick with Foo, Bar, Baz or Appple, Pear, Banana.
If you are not getting an NPE then I expect your mocking/spying is interfering. If you call the code under test without mocking/spying the call chain would be:
CodeWithPrivateMethod.startGamble();
->
CodeWithYetAnotherPrivateMethod value = CodeWithAnotherPrivateMethod.getGambleValue();
->
return null;
<-
value.getGambling();
<- throws NullPointerException
What exactly are you trying to find out or achieve?
EDIT: Here's how it should work with PowerMock
#RunWith(PowerMockRunner.class)
#PrepareForTest(CodeWithAnotherPrivateMethod.class)
public class CodeWithPrivateMethodTest {
#Mock
private CodeWithYetAnotherPrivateMethod yetAnotherInstance;
#Test
public final void testStartGamble() {
// SETUP
mockStatic(CodeWithAnotherPrivateMethod.class);
expect(CodeWithAnotherPrivateMethod.getGambleValue())
.andReturn(yetAnotherInstance);
Boolean gamblingValue = true;
expect(yetAnotherInstance.getGambling()).andReturn(gamblingValue);
replayAll();
// CALL
CodeWithPrivateMethod.startGamble();
// VERIFY
verifyAll();
}

JMockit `Mockup` class returns null for own new instances from within itself [duplicate]

I have a static method which will be invoking from test method in a class as bellow
public class MyClass
{
private static boolean mockMethod( String input )
{
boolean value;
//do something to value
return value;
}
public static boolean methodToTest()
{
boolean getVal = mockMethod( "input" );
//do something to getVal
return getVal;
}
}
I want to write a test case for method methodToTest by mocking mockMethod.
Tried as bellow and it doesn't give any output
#Before
public void init()
{
Mockit.setUpMock( MyClass.class, MyClassMocked.class );
}
public static class MyClassMocked extends MockUp<MyClass>
{
#Mock
private static boolean mockMethod( String input )
{
return true;
}
}
#Test
public void testMethodToTest()
{
assertTrue( ( MyClass.methodToTest() );
}
To mock your static method:
new MockUp<MyClass>()
{
#Mock
boolean mockMethod( String input ) // no access modifier required
{
return true;
}
};
To mock the static private method:
#Mocked({"mockMethod"})
MyClass myClass;
String result;
#Before
public void init()
{
new Expectations(myClass)
{
{
invoke(MyClass.class, "mockMethod", anyString);
returns(result);
}
}
}
#Test
public void testMethodToTest()
{
result = "true"; // Replace result with what you want to test...
assertTrue( ( MyClass.methodToTest() );
}
From JavaDoc:
Object mockit.Invocations.invoke(Class methodOwner, String methodName, Object... methodArgs)
Specifies an expected invocation to a given static method, with a given list of arguments.
There is another way of mocking static methods using JMockit (using Delegate class). I find it more convenient and elegant.
public class Service {
public String addSuffix(String str) { // method to be tested
return Utils.staticMethod(str);
}
}
public class Utils {
public static String staticMethod(String s) { // method to be mocked
String suffix = DatabaseManager.findSuffix("default_suffix");
return s.concat(suffix);
}
}
public class Test {
#Tested
Service service;
#Mocked
Utils utils; // #Mocked will make sure all methods will be mocked (including static methods)
#Test
public void test() {
new Expectations {{
Utils.staticMethod(anyString); times = 1; result = new Delegate() {
public static String staticMethod(String s) { // should have the same signature (method name and parameters) as Utils#staticMethod
return ""; // provide custom implementation for your Utils#staticMethod
}
}
}}
service.addSuffix("test_value");
new Verifications {{
String s;
Utils.staticMethod(s = withCapture()); times = 1;
assertEquals("test_value", s); // assert that Service#addSuffix propagated "test_value" to Utils#staticMethod
}}
}
}
Reference:
https://jmockit.github.io/tutorial/Mocking.html#delegates
https://jmockit.github.io/tutorial/Mocking.html#withCapture

Verify method in constructor was called

I have a constructor that calls a method, like this:
public Foo(boolean runExtraStuff) {
if (runExtraStuff){
doExtraStuff();
}
}
The doExtraStuff() method is running some additional commands that are not easily mocked themselves (things like database checks to initialize some variables). Perhaps it would be better for the constructor to not do this, but this is the code I have to work with at the moment.
I would like to create a unit test to make sure that doExtraStuff() is called when the boolean runExtraStuff is true and does not run when the boolean is false. I am using JMockit.
However, I'm not sure how to make this happen. Normally I would use a Verifications on a mocked object, but since I am testing the constructor, I can't use a mocked object in this way. So how can I verify that a method within a constructor was called?
It's easy enough, even if it requires partial mocking:
#Test
public void runsSetupWhenRequestedOnFooInitialization()
{
// Partially mocks the class under test:
new Expectations(Foo.class) {};
final Foo foo = new Foo(true);
// Assuming "setup" is not private (if it is, use Deencapsulation.invoke):
new Verifications() {{ foo.setup(); }};
}
#Test
public void doesNotRunSetupWhenNotRequestedOnFooInitialization()
{
new Expectations(Foo.class) {};
final Foo foo = new Foo(false);
new Verifications() {{ foo.setup(); times = 0; }};
}
Of course, it would probably be better to avoid mocking in a case like this; instead, the test should check the state of the object through getters or other available methods, if at all possible.
Well, the straightforward answer doesn't use JMockit at all..
in src/main/java/example..
package example;
public class Foo {
private boolean setupRan = false;
public Foo(boolean runSetup) {
if (runSetup) setup();
}
public void setup() {
setupRan = true;
}
public boolean getSetupRan() {
return setupRan;
}
}
in src/test/java/example..
package example;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
public class FooTest {
private Foo testSubject;
#Test
public void should_run_setup() {
testSubject = new Foo(true);
assertThat(testSubject.getSetupRan()).isTrue();
}
#Test
public void should_not_run_setup() {
testSubject = new Foo(false);
assertThat(testSubject.getSetupRan()).isFalse();
}
}
I'll go out on a limb and guess that you are interested in a partial mock here:
in src/main/java/example..
package example;
public class Foo1 {
public Foo1(boolean runSetup) {
if (runSetup) setup();
}
public void setup() {
System.out.println("in setup()");
}
}
in src/test/java/example..
package example;
import static org.assertj.core.api.Assertions.*;
import mockit.Expectations;
import mockit.Mocked;
import org.junit.Test;
public class Foo1Test {
// hateful partial mocking of test subject!
#Mocked({"setup()"})
private Foo1 testSubject;
#Test
public void should_run_setup() {
new Expectations() {{
testSubject.setup(); // setup() is called
}};
testSubject = new Foo1(true);
}
#Test
public void should_not_run_setup() {
new Expectations() {{
testSubject.setup(); times = 0;
}};
testSubject = new Foo1(false);
}
}
EDIT 1: Note that you won't see the println output since the method was mocked.
EDIT 2: Set expectations for invocations of testSubject.setup() to times = 0 in second test

Define expectations for public final instance variable

I'm new at unit testing and am running into an issue with jMock that I can't seem to figure out. I have a public final instance variable which I need to define an expectation for, but I can't get it to work. If I make a getter for the variable, it works, but I'd rather not have to create a bunch of getters just to make unit testing work. Any help on how to do this would be much appreciated. Here's some code illustraiting what I'm trying to do:
public class Main {
private SimpleObject simpleObject;
public Main(SimpleObject o){
this.simpleObject = o;
}
public int iDontWork(){
return simpleObject.myList.size();
}
public int iWork(){
return simpleObject.getMyList().size();
}
}
My test:
#RunWith(JMock.class)
public class MainTest {
Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
#Mock
SimpleObject simpleObject;
private Main main;
#Before
public void setup(){
main = new Main(simpleObject);
}
#Test
public void itWorks() {
context.checking(new Expectations() {{
oneOf(simpleObject).getMyList();
will(returnValue(new ArrayList<String>(Arrays.asList("Hey"))));
}});
int i = main.iWork();
assertEquals(1, i);
}
#Test
public void itDoesntWork() {
context.checking(new Expectations() {{
oneOf(simpleObject).myList.size(); will(returnValue(1));
}});
int i = main.iDontWork();
assertEquals(1, i);
}
}
SimpleObject:
public class SimpleObject {
public final List<String> myList;
public SimpleObject(){
myList = Collections.unmodifiableList(Arrays.asList("Hey"));
}
public List<String> getMyList(){
return myList;
}
}
A mock object implements methods of the real object. It does not have fields of the real object (even if these fields are public).

Categories