I have some code like this:
class FooBar {
private String stateFoo;
public FooBar(String stateFoo){
this.stateFoo = stateFoo;
}
public void foo() {
FooInst f = FooInstFactory.createSomeFooInst(AnotherStaticFooConfig.getSomePath);
f.justCountMe();
}
}
My goal is to make sure that f.justCountMe() was executed exactly once. I know how to do it in general with mockito.
What I don't know is how do I inject a mocked version of FooInst into the foo method? So that I can count the invocation?
Is it even possible to do so?
You need to use powermockito and mock static method. See explanation how to do this here
PowerMockito mock single static method and return object
If possible; I suggest to avoid using mocking libraries that temper with static fields (in the way PowerMock/Mockito do) - as it often comes with undesired side effects (for example many "coverage" tools produce invalid results when static mocking takes places).
So my suggestion: re-design your class under test. Instead of fetching f from a static factory; provide a constructor for either the factory or f; then you can mock the corresponding object; without the need to turn to the mighty but dangerous "Powerxyz" stuff.
Related
I'm trying to work out how to verify the parameters passed to a mocked constructor in Mockito. A simplified version of my code is:
class Mocked {
Mocked(String first, String second, int value) {
}
}
class Target {
void testMe() {
new Mocked("Hello", "World", 99);
}
}
#Test
public void test_Target() {
try (
MockedConstruction<Mocked> mockedNew = mockConstruction(Mocked.class);
) {
new Target().testMe();
Mocked mocked = mockedNew.constructed().get(0);
// TODO: verify all arguments passed to mocked
}
}
The class I'm trying to test is "Target"
Target uses an instance of the "Mocked" class. In real code code I'll want to use an actual instance of Mocked, but for the purposes of testing I want to mock it out so I can test "Target" in isolation of "Mocked". I've used the mockConstruction construct to do this.
In my final version of my code the arguments passed to the Mocked constructor are not hardcoded. Instead there will be some business logic to derive them, so and I want to verify they have been derived out correctly. But how?
None of the examples I've Googled show show me how to do this, and org.mockito.Mockito.verify() doesn't appear to have a way to test a constructor.
The only solution I can see is to add mock initialiser function that copies the argument into local variables. But this involves making those variables effectively final (so final one element array) and ugly casts. Surely there has to be something better than that!
What have I missed?
As far as I know, this is not possible using the Mockito API.
You can try a design change where a new MockedFactory class is responsible for creating Mocked objects. You can create a MockMockedFactory for your tests and inject it into Target to use. You will be able to verify the methods called on this factory by the class under test. Not the nicest, adds boilerplate code, but works.
Also, I guess the newly created object is not returned as testing would not be a problem then. It is worth considering if the method you are testing isn't too big doing too many things at once. Maybe some other refactors could help make it more testable.
Or maybe this one: https://groups.google.com/g/mockito/c/WqPlcNrvbOw?pli=1
I started using JUnits (Mockito) from yesterday. I searched for similar question, but didn't find.
I have a class with method method1() which in turn calls method2().
I don't want to mock method2
I am mocking call to method1(). I was expecting that it would return the custom object(without going ahead and calling method2) which I want. But instead it proceeds and tries to call method2().
class A {
method1() {
//do something.
method2();
}
}
I mocked method1 and return any object (say new Integer(1)).
I dont want method2 to be called. but when I am debugging this Junit. It goes and calls method2. Hence fails.
When using syntax like this:
#Test public void yourTest() {
A mockA = Mockito.mock(A.class, Mockito.CALLS_REAL_METHODS);
when(mockA.method1()).thenReturn(Integer.valueOf(1));
}
then the first thing Java will do is to evaluate when(mockA.method1()), which requires calling mockA.method1() to get a value to pass into when. You don't notice this with other mocks, because Mockito mocks return nice default values, but with spies and CALLS_REAL_METHODS mocks this is a much bigger problem. Clearly, this syntax won't work.
Instead, use the methods beginning with do:
#Test public void yourTest() {
A mockA = Mockito.mock(A.class, Mockito.CALLS_REAL_METHODS);
doReturn(Integer.valueOf(1)).when(mockA).method1();
}
As part of .when(mockA), Mockito will instead return an instance that has no behavior, so the call to method1() never happens on a real instance. do syntax also works with void methods, which makes it more flexible than when(...).thenReturn(...) syntax. Some developers advocate for using doReturn all the time; I prefer thenReturn because it's slightly easier to read, and can also do return type checking for you.
As a side note, prefer Integer.valueOf(1) over new Integer(1) unless you absolutely need a brand new instance. Java keeps a cache of small integers, and this can be faster than allocating a brand new reference if you need to manually box an int into an Integer.
Usually you mock interfaces or abstract classes and provide implementations of abstract methods. In your case you want to substitute the real implementation of a concrete class. This can be achieved via partial mocks.
http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#16
I have a method like this:
public void someMethod() {
A a = new A(); // Where A is some class.
a.setVar1(20);
a.someMethod();
}
I want to test 2 things:
The value of Var1 member variable of a is 20.
someMethod() is called exactly once.
I have 2 questions:
Are those test objectives correct or should I be testing something else ?
How exactly do I test this using Mockito ?
You can't test that using Mockito, because Mockito can't access a local variable that your code creates and then let go out of scope.
You could test the method if A was a injected dependency of your class under test, or of the method under test
public class MyClass {
private A a;
public MyClass(A a) {
this.a = a;
}
public void someMethod() {
a.setVar1(20);
a.someMethod();
}
}
In that case, you could create a mock A, then create an instance of MyClass with this mock A, call the method and verify if the mock A has been called.
With your code, as it is, the only way to test the code is to verify the side effects of calling someMethod() on an A with var1 equal to 20. If A.setVar1() and A.someMethod() don't have any side-effect, then the code is useless: it creates an object, modifies it, and forgets about it.
Use JB Nizet's advice but note that order is important to you:
When verifying and order is important, use:
A mock = mock(A);
new MyClass(mock).someMethod();
InOrder order = inOrder(mock);
order.verify(mock).setVar1(20);
order.verify(mock).someMethod();
(Testing for exactly one invocation is the default in mockito).
Caution
This kind of test will be tightly coupled to the implementation. So do this in moderation. In general aim for testing state rather than implementation where possible.
Ad 1) Testing setters usually doesn't make much sense, but if you want to to then surely you have a getter on A to verify that var1 is set to 20?
Ad 2) You can use #Spy and verify() to test invocations on methods.
A spy = spy( a );
verify( spy , times( 1 ) ).someMethod();
Your example code is a bit terse, so my answer is very general - hope you can work with it.
Cheers,
I have following class:
public class LegacyClass()
{
public LegacyClass(final int aModeOfOperation)
{
if (aModeOfOperation == 0)
{
addSomeValues();
addSomeValues();
}
else if (aModeOfOperation == 1)
{
addSomeValues();
}
}
private void addSomeValues()
{
}
}
I want to write a unit test, which would check that
the call LegacyClass(0) causes the private method addSomeValues to be called 2 times and
the call LegacyClass(1) causes the private method addSomeValues to be called once.
I know that it is possible to use spy objects in Mockito/PowerMockito to count the number of private method calls, but AFAIK these approaches work only if the methods in question are called after the construction of the tested class.
Is it possible to write the unit test described above without changing the constructor of LegacyClass ?
I think you get much better value out of unit testing if you can perform state based testing (http://blog.jayfields.com/2008/02/state-based-testing.html?m=1) on the requirements/behavior of a public methods rather than testing the number of invocation of a private methods. This might be possible in some isolation frameworks, but from the unit testing point of view I don't see much value.
Think about that some unit test, you would verify a method has been called, or a method has been called x numbers if times. These tests are verification testing and they are still valid. BUT the key factor is most of the mock object frameworks allows you to do these verification against public methods (at least in .net) . The reason is that private methods are not really important from the unit testing point of view because they internal implementation detail. Try to avoid test failures for code schematics change.
I don't think it's possible using mockito, as you declare the spy this way spy(new LegacyClass()), hence your constructor is called before the object is spied. Maybe there's a way with PoweverMock but I usually discourage the use of PowerMock because no effort is put in refactoring code to a proper design.
Instead I highly recommend you to refactor your legacy code to something more testable (Test-Driven-Developement is he key here).
If you absolutely need to keep this legacy code with compatible changes but without PowerMock ; I would first instead increase the visibility level to package visible :
private void addSomeValues() { ... }
Then write a static subclass of LegacyClass in your test, and override the addSomeValues method that will increase a counter the call super.
public class LegacyCodeTest {
...
static class AddSomeValuesCounteringLegacyClass extends LegacyClass {
public int counter;
void addSomeValues() { counter = counter + 1; super.addSomeValues(); }
}
}
Then in your test you insatiate this class and assert the call count;
I want to mock a concrete class in a TestNG test case. The class could look like this (simplified example):
public class Example() {
private MyHello myHello;
public Example(MyHello myHello) {
this.myHello = myHello;
}
public String doSomething() {
return myHello.doSomethingElse();
}
}
Now we want to mock Example return some defined value:
#BeforeMethod
public void setUp() {
this.example = mock(Example.class);
when(this.example.doSomething()).thenReturn("dummyValue");
}
This looks quite good but in fact it isn't. The last line in the setup method calls the method on an instance of Example, this instance didn't get an MyHello through the constructor and so I get a NPE in the setUp method.
Is there a way to either inject an MyHello while creating the mock or to disallow Mockito calling the method on a real instance?
Edit
The issue, that caused the observed behaviour was, that the doSomething() method is actually final. I overlooked that when I tried to solve that issue. And this is a known limitation with mockito anyway. So I'll either remove the finals or extract an interface for that class.
See if using doReturn("dummy").when(example).doSomething() does the trick.
Mockito.doReturn
From JavaDoc:
Use doReturn() in those rare occasions when you cannot use when(Object).
Beware that when(Object) is always recommended for stubbing because it is argument type-safe and more readable (especially when stubbing consecutive calls).
Here are those rare occasions when doReturn() comes handy:
When spying real objects and calling real methods on a spy brings side effects
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing:
doReturn("foo").when(spy).get(0);
You can benefit from spy keyword instead of mock.
As far as I'm concerned from the documentation of Mockito, you are able to make partial mock with spy.
For detailed explanation you can benefit from subject 13 in the doc of it.