Verifying non spy method calls with Spock - groovy

I want to use spock to find if a method in a class was called. But when I try to verify it, the when block says that the method was never called.
public class Bill {
public Bill(Integer amount) {
this.amount = amount;
}
public void pay(PaymentMethod method) {
Integer finalAmount = amount + calculateTaxes();
method.debit(finalAmount);
}
private Integer calculateTaxes() {
return 0;
}
private final Integer amount;
}
public class PaymentMethod {
public void debit(Integer amount) {
// TODO
}
public void credit(Integer amount) {
// TODO
}
}
import spock.lang.Specification
import spock.lang.Subject
class BillSpec extends Specification {
#Subject
def bill = new Bill(100)
def "Test if charge calculated"() {
given:
PaymentMethod method = Mock()
when:
bill.pay(method)
then:
1 * method.debit(100)
// 1 * bill.calculateTaxes() // Fails with (0 invocations) error
0 * _
}
}
In the example above all I want to do is verify if calculateTaxes is being called but the test fails with (0 invocations). I tried using spy but am not sure what would be the syntax since Bill takes a parameterized constructor.

You can test calculateTaxes() call when you Spy the Bill instance like this:
class SpyTestSpec extends Specification {
def "Test if charge calculated"() {
given:
def bill = Spy(new Bill(100))
PaymentMethod method = Mock()
when:
bill.pay(method)
then:
1 * method.debit(100)
1 * bill.calculateTaxes()
1 * bill.pay(method)
0 * _
}
}
Another important thing is to make calculateTaxes() method visible for the test, otherwise it will still fail:
public Integer calculateTaxes() { ... }
Note that if you want to test that nothing else was called then you should also add:
1 * bill.pay(method)
And here is the result:

Related

JUnit 5 Mockito Stubbing Referenced Method and Verifying it was Called

I'm working with JUnit5 and their ParameterizedTest feature. How do I work with method references as part of the data source?
Example:
public enum Status {
APPROVE, DECLINE
}
#Mock
public MockService mockService;
// Normal Test
#Test
void testApprove() {
Mockito.doReturn(null)
.when(mockService)
.approveCall();
Mockito.verify(mockService).approveCall();
}
// Parameterized Test
Map<Status, Supplier<?>> mockMap = Map.ofEntries( // Java 9 method
Map.entry(APPROVE, mockService::approveCall),
Map.entry(DECLINE, mockService::declineCall)
);
#ParameterizedTest
#EnumSource(Status.class)
void test(Status status) {
Supplier<?> supplier = mockMap.get(status);
??
}
I want my second test to do the same thing as my first test, but also covering the DECLINE value. How do I parameterize the mock method reference?
I worked around it with a few functional/lambda tricks.
public class MyTest {
public enum Status {
APPROVE, DECLINE
}
#Mock
public MockService mockService;
// Parameterized Test
Map<Status, MockitoVerifier> mockMap = Map.ofEntries( // Java 9 method
Map.entry(Status.APPROVE, () -> Mockito.verify(mockService).approveCall()),
Map.entry(Status.DECLINE, () -> Mockito.verify(mockService).declineCall())
);
#ParameterizedTest
#EnumSource(Status.class)
void test(Status status) {
MockitoVerifier<?> verifier = mockMap.get(status);
verifier.verify();
}
#FunctionalInterface
interface MockitoVerifier<T> {
T verify();
}
}

How to mock a object construction that is created using reflection i.e newInstance() method

I have a piece of code below where Employee class creates object of AppraisalCalculator using reflection. I want to mock this AppraisalCalculator object using PowerMockito.
class AppraisalCalculator {
public int appraisal() {
return 300;
}
}
class Employee {
public int updateSalary() {
// line 1
AppraisalCalculator ac =
AppraisalCalculator.class.getConstructor().newInstance();
return ac.appraisal();
}
}
class TestRunner {
#Test
public void test() {
AppraisalCalulator acMock=PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue=600;
Assert.equals(expectedValue,actualValue);
}
}
Here, even though I have mocked the Appraisal calculator object, it still calls the real appraisal() method from AppraisalCalculator. If the actual AppraisalCalculator at line 1 is created using new Operator instead of newInstance() then this mocking works.
Can anyone explain why this is not working if the actual object is created using reflection? What can I do to mock this Object in such scenario?
Let me first start by rephrasing your question will fully working code.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Employee.class)
public class TestRunner {
#Test
public void test() throws Exception {
AppraisalCalculator acMock = PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(acMock);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
}
Then, the way PowerMock works is that the PowerMockRunner will look at each class that needs to be prepared (here Employee), then look for a call to the constructor we want to replace and do it. This is done at class loading. The real class bytecode calling the constructor is replaced by the one returning the mock.
The thing is that if you are using reflection, PowerMock can't know by reading the bytecode that this constructor will be called. It will only be known dynamically afterwards. So no mocking done.
If you really do need to create the class to be mocked by reflection, I would actually refactor the code a bit.
In Employee I would add something like
protected AppraisalCalculator getCalculator() {
try {
return AppraisalCalculator.class.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
while is a method dedicated to isolate the calculator construction.
The, just create a child class
#Test
public void testWithChildClass() {
// Note that you don't need PowerMock anymore
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee() {
#Override
protected AppraisalCalculator getCalculator() {
return acMock;
}
};
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
or a partial mock (spy)
#Test
public void test2() {
// No PowerMock either here
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = spy(new Employee());
doReturn(acMock).when(emp).getCalculator();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}

InvalidCountException: Method should be called exactly 1 times but called 0 times

when I run test with mockery on laravel, this error message:
Mockery\Exception\InvalidCountException: Method findOrFail(1) from Mockery_0__Customer should be called exactly 1 times but called 0 times
TestCase
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
}
protected function seeJsonValidFailedResponse()
{
print_r($this->response->getContent());
$this->assertEquals(400, $this->response->status());
return $this;
}
protected function seeJsonValidResponse()
{
print_r($this->response->getContent());
$this->assertEquals(200, $this->response->status());
return $this;
}
public function setUp()
{
parent::setUp();
}
public function tearDown()
{
parent::tearDown();
}
CustomerTest
use Mockery;
class CustomerTest extends TestCase
{
use WithoutMiddleware;
public function testIndexSuccess()
{
$idCustomer= 1;
$mockCustomer = Mockery::mock('Customer');
$mockCustomer
->shouldReceive('findOrFail')
->once()
->with($idCustomer)
->andReturn(true);
$this->app->instance('Customer', $mockCustomer);
$this->get('/customer/history/' . $idCustomer)
->seeJsonValidResponse();
}
}
Controller
use App\Customer;
class CustomerController extends Controller
{
public function __construct(Customer $customer) {
$this->customerModel = $customer;
}
public function history($id)
{
$customer = $this->customerModel->findOrFail($id);
$issues = $customer->issues();
return view('customer/history', compact('customer', 'issues'));
}
}
You should add the whole namespace for the Customer class when defining the mock. So change this line:
$mockCustomer = Mockery::mock('Customer');
to this:
$mockCustomer = Mockery::mock('App\Customer');

Are accessors / mutators auto-defined in Groovy?

In the section on handling Java Beans with Groovy of Groovy In Action, I found this script (slightly modified):
class Book{
String title
}
def groovyBook = new Book()
// explicit way
groovyBook.setTitle('What the heck, really ?')
println groovyBook.getTitle()
// short-hand way
groovyBook.title = 'I am so confused'
println groovyBook.title
There are no such methods in the class Book so how does that work ?
Yes, they are auto defined and calling book.title is actually calling book.getTitle()
See http://groovy.codehaus.org/Groovy+Beans
You can see this in action with the following script:
def debug( clazz ) {
println '----'
clazz.metaClass.methods.findAll { it.name.endsWith( 'Name' ) || it.name.endsWith( 'Age' ) }.each { println it }
}
class A {
String name
int age
}
debug( A )
// Prints
// public int A.getAge()
// public java.lang.String A.getName()
// public void A.setAge(int)
// public void A.setName(java.lang.String)
// Make name final
class B {
final String name
int age
}
debug( B )
// Prints
// public int B.getAge()
// public java.lang.String B.getName()
// public void B.setAge(int)
// Make name private
class C {
private String name
int age
}
debug( C )
// Prints
// public int C.getAge()
// public void C.setAge(int)
// Try protected
class D {
protected String name
int age
}
debug( D )
// Prints
// public int D.getAge()
// public void D.setAge(int)
// And public?
class E {
public String name
int age
}
debug( E )
// Prints
// public int E.getAge()
// public void E.setAge(int)
Several notes:
For all property fields(public ones only), there are autogenerated accesors.
Default visibility is public. So, you should use private/protected keyword to restrict accessor generation.
Inside an accessor there is direct field access. like this.#title
Inside a constructor you have direct access to! This may be unexpected.
For boolean values there are two getters with is and get prefixes.
Each method with such prefixes, even java ones are treated as accessor, and can be referenced in groovy using short syntax.
But sometimes, if you have ambiguous call there may be class cast exception.
Example code for 4-th point.
class A{
private int i = 0;
A(){
i = 4
println("Constructor has direct access. i = $i")
}
void setI(int val) { i = val; println("i is set to $i"); }
int getI(){i}
}
def a = new A() // Constructor has direct access. i = 4
a.i = 5 // i is set to 5
println a.i // 5
​
4-th note is important, if you have some logic in accessor, and want it to be applied every time you call it. So in constructor you should explicit call setI() method!
Example for 7
class A{
private int i = 0;
void setI(String val) { println("String version.")}
void setI(int val) { i = val; println("i is set to $i"); }
}
def a = new A()
a.i = 5 // i is set to 5
a.i = "1s5" // GroovyCastException: Cannot cast object '1s5' with class 'java.lang.String' to class 'int'
​
So, as I see property-like access uses first declared accessor, and don't support overloading. Maybe will be fixed later.
Groovy generates public accessor / mutator methods for fields when and only when there is no access modifier present. For fields declared as public, private or protected no getters and setters will be created.
For fields declared as final only accessors will be created.
All that applies for static fields analogously.

Calling method from overridden Java class.

I have a problem with calling an overriden method from java class.
I have the following Java class:
public class Base
{
int state = 0;
public void called()
{
System.out.println("Hello, from called method: " + state);
}
public String getFirst()
{
return "From Base;
}
//
...
//
}
I use a groovy script to override getFirst() that so that it calls called()
def base = [ getFirst : {
called() // this line has an error
"From Second"
}] as Base
base.getFirst()
How do I implement the this?
You can't use the proxy magic in that way... At the time of the Maps declaration, it doesn't know it's going to be a Proxy for Base, so it will throw the error
Why not just do it the normal way?
def base = new Base() {
public String getFirst() {
called()
"from me"
}
}

Resources