1

I want to mock the following class using JMockit:

public class A { private int n; public A(int n) { this.n = n; } public boolean isCorrect() { return n % 2 == 0; } } 

The class is initialized throughout my code, and I usually don't have access to that part of the code in my test.
At some of my tests I want to mock it so that if the class is initialized with the value of 3, 'isCorrect' will return true (which is not the normal behavior), and at some other tests I want to mock it so that 'isCorrect' will return false no matter how it was initialized.

I tried to find a way to do it in the documentation, but it wasn't so user-friendly and I gave up on it.

2 Answers 2

5

For your first case, you can do:

new MockUp<A> () { private int n; @Mock public void $init(int n) { this.n = n; } @Mock public boolean isCorrect() { return n == 3; } }; 

And for your second example:

new MockUp<A> () { @Mock public boolean isCorrect() { return false; } }; 

For example, this prints false, true, false, false:

new MockUp<A> () { private int n; @Mock public void $init(int n) { this.n = n; } @Mock public boolean isCorrect() { return n == 3; } }; System.out.println(new A(2).isCorrect()); System.out.println(new A(3).isCorrect()); new MockUp<A> () { @Mock public boolean isCorrect() { return false; } }; System.out.println(new A(2).isCorrect()); System.out.println(new A(3).isCorrect()); 

EDIT

Following your comment, one way to mock the class only for certain values of n is to use reflection to check the value of the field:

new MockUp<A> () { @Mock public boolean isCorrect(Invocation invocation) { // Gets the invoked instance. A a = invocation.getInvokedInstance(); int n = Deencapsulation.getField(a, "n"); if (n == 3) return true; else return a.isCorrect(); } }; 

But it becomes a bit fragile because it depends on the name of the variable in your class A.

A maybe better alternative would be to give a package-protected getter for testing purposes in your class A: int getN() { return n; } and you don't need reflection any more.

Sign up to request clarification or add additional context in comments.

2 Comments

Your second example (always return false) works great, but not the first one. I want the mocked class to return true for 3, but behave normally for all other cases (without re-writing the original logic in the mock), and I also don't want to ignore what the original constructor is doing (only add logic to it at most).
I've added an answer with what seems to me a better solution.
-3

Thanks @assylias for you answer. I think I found a better way to implement the first mock, which combines the ideas from your first and second (after edit) answers. It goes like this:

new MockUp<A> () { private int n; @Mock public void $init(Invocation inv, int n) { this.n = n; inv.proceed(); } @Mock public boolean isCorrect(Invocation inv) { if (n == 3) { return true; } return inv.proceed(); } }; 

Update

For the second mock (the brute false return), this will do:

new MockUp<A> () { @Mock public boolean isCorrect() { return false; } }; 

And again, thanks to @assylias for helping me with this :)

1 Comment

I've noticed that users keep down-voting this answer, but without any explanation. This is still the preferable way IMHO, since @assylias answer depends on the field name, while this one doesn't (s/he even writes But it becomes a bit fragile because it depends on the name of the variable in your class A). Can anyone come up with the reason why this is a less preferable answer?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.