Spock fails when PostConstruct calls a injected service - grails

Can any one tell me how to solve the issue of PostConstruct get called before mocking:
Service:
class MyService {
SecondService secondService // injected
#PostConstruct
void init() {
myFunction()
}
void myFunction() {
secondService.doSomething()
}
}
Test:
#TestFor(MyService)
class MyServiceSpec extends Specification {
void "testing my service"() {
given:
MyService service = GroovySpy(MyService) {
myFunction() >> null
}
then:
true
}
}
Gives following error:
Invocation of init method failed; nested exception is java.lang.NullPointerException: Cannot invoke method doSomething() on null object

If you have #TestFor(MyService) - MyService instance will be created automatically and you can use it as 'service'. And you don't need to create MyService manually.
So you can only delete #TestFor(MyService) or use it and remove MyService service.
But you also need to correctly mock 'secondService'
#FreshRuntime
#TestFor(MyService)
class MyServiceSpec extends Specification {
def secondService = GroovyMock(SecondService)
def doWithSpring = {
secondService(InstanceFactoryBean, secondService, SecondService)
}
void "testing my service"() {
when:
service.myFunction()
then:
1 * secondService.doSomething()
}
}

Related

Micronaut #Replaces with declarative Client

I am going to use the code from Micronaut Documentation (Declarative Http Client)- And I'm using Spock
PetOperations.java
#Validated
public interface PetOperations {
#Post
Single<Pet> save(#NotBlank String name, #Min(1L) int age);
}
I have a declarative client:
#Client("/pets")
public interface PetClient extends PetOperations {
#Override
Single<Pet> save(String name, int age);
}
My goal is when I run a test class, I want to call (#Replaces) another class (PetDummy) instead of the PetClient, PetDummy class is located in my test folder
#Primary
#Replaces(PetClient.class)
#Singleton
public class PetDummy implements PetOperations {
#Override
public Single<Pet> save(String name, int age) {
Pet pet = new Pet();
pet.setName(name);
pet.setAge(age);
// save to database or something
return Single.just(pet);
}
}
test class:
class PetTest extends Specification {
#Shared
#AutoCleanup
ApplicationContext applicationContext = ApplicationContext.run();
//EmbeddedServer server = applicationContext.getBean(EmbeddedServer.class).start();
PetClient client = applicationContext.getBean(PetOperations.class);
def 'test' (){
given: 'name and age'
when:
client.save("Hoppie", 1);
then:
noExceptionThrown()
}
}
However, at the end PetClient is called, I have as well tried with the #Factory annotation, but no success
PetClient extends PetOperations and PetDummy implements PetOperations, if they both implement then it will make sense to use #Replaces ...
Is there something else I can try out?
Thank you!
Another Issue:
Now that it works, the PetClient is a dependency in my PetService. When I test my PetService, it still calls the PetClient instead of the PetDummy.
I assume it has to do with the applicationContext, you will see
PetService:
PetService {
#Inject
PetClient client;
buyFood(){
//...
Single<Pet> pet = client.save("Hoppie", 1));
}
}
PerService Test:
class PetServiceTest extends ApplicationContextSpecification {
#Subject
#Shared
PetService petService = applicationContext.getBean(PetService)
PetOperations client = applicationContext.getBean(PetOperations.class) //client is not used here
def 'test' (){
given:
when:
petService.buyFood()
then:
noExceptionThrown()
}
}
I think that I need to "get into" the applicationContext from the PetService, to tell "use the PetDummy" implementation (Inside the test class, because the ApplicationContextSpecification belong to another module
The ApplicationContextSpecification is:
abstract class ApplicationContextSpecification extends Specification implements ConfigurationFixture {
#AutoCleanup
#Shared
ApplicationContext applicationContext = ApplicationContext.run(configuration)
/* def cleanup() {
assert !hasLeakage()
}*/
}
The ConfigurationFixture contains the properties for the database(hibernate)
You are already retrieving the PetClient bean implementation:
PetClient client = applicationContext.getBean(PetOperations.class);
Which should provide the replacing dummy bean implementation if called with the appropriate type:
PetOperations client = applicationContext.getBean(PetOperations.class);

Unable to override LoginController's authFail()

I need to customize message so I tried to modify the LoginController by simply overriding the grails .plugin.springsecurity.LoginController
I have thrown AccountNotApprovedException from my customizedAuthenticationProvider.
Can someone suggest me what I am missing?
class AccountNotApprovedException extends AuthenticationException{
public AccountNotApprovedException(String message, Throwable t) {
super(message, t)
}
public AccountNotApprovedException(String message) {
super(message)
}
/** #deprecated */
#Deprecated
public AccountNotApprovedException(String message, Object extraInformation) {
super(message, extraInformation)
}
}
I override the loginController:-
class LoginController extends grails.plugin.springsecurity.LoginController {
def authenticationTrustResolver
/**
* Dependency injection for the springSecurityService.
*/
def springSecurityService
def authfail() {
//my customized code
}
}
And when springSecurity runs then it didn't call my overridden authFail()

How to test class with #Autowired using Spock

I have a class in src/groovy like this
public class MyClass {
#AutoWired
SomeOtherClass someOtherClass
String test() {
return someOtherClass.testMethod()
}
}
When I write a test for this method I am getting an error: Cannot invoke method testMethod() on null object.
This is my test :-
def "test test" () {
expect:
myClass.test() == "somevalue"
}
What am I doing wrong? Is there a way to mock the #Autowired class?
You need to mock your someOtherClass. Something like this
def "test test"(){
setup:
myClass.someOtherClass = Mock(SomeOtherClass)
myClass.someOtherClass.testMethod() >> "somevalue"
expect:
myClass.test() == "somevalue"
}
Though the previous answer should work, spock provide more elegant way of injecting beans as per need. You could use doWithSpring closure to declare beans just like spring dsl support provided in grails using resources.groovy.
class MyClass extends Specification{
def setup(){
static doWithSpring={
someOtherClass(SomeOtherClass)
//declare below if want to inject myClass somewhere else as a bean else not
/*myClass(MyClass){bean->
someOtherClass = someOtherClass
}*/
}
}
def "test test" () {
expect:
myClass.test() == "somevalue"
}
}

Getting "Too few invocations" on unit test with spock

For simplicity let's take a very simple class:
public class TestingClass {
public void method1(){
System.out.println("Running method 1");
method2();
}
public void method2(){
System.out.println("Running method 2");
}
}
Now I'm writing a simple test, which checking that when we invoke method1(), method2() is invoked:
class TestingClassSpec extends Specification {
void "method2() is invoked by method1()"() {
given:
def tesingClass = new TestingClass()
when:
tesingClass.method1()
then:
1 * tesingClass.method2()
}
}
by executing this test, I'm getting the following error:
Running method 1 Running method 2
Too few invocations for:
1 * tesingClass.method2() (0 invocations)
Why I'm getting this error? Printed log is show that method2() was invoked.
You need to use Spy when testing interactions on real objects, see below:
#Grab('org.spockframework:spock-core:0.7-groovy-2.0')
#Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class TestingClassSpec extends Specification {
void "method2() is invoked by method1()"() {
given:
TestingClass tesingClass = Spy()
when:
tesingClass.method1()
then:
1 * tesingClass.method2()
}
}
public class TestingClass {
public void method1(){
System.out.println("Running method 1");
method2();
}
public void method2(){
System.out.println("Running method 2");
}
}

Dependency Injection with PowerMock & Mockito

How do I create a JUnit testcase for the following class with PowerMock & Mockito.
The class I want to inject is a final class so I'll need to use PowerMock to mock it.
Also note I would prefer to use DI rather than a setter to inject it.
import javax.inject.Inject;
public class ObjectA {
// Use DI to Inject a mock for this 'final' class
#Inject
private ObjectB objectB;
public ObjectA() {
}
public void someMethod() {
if (null == this.objectB) {
throw new IllegalStateException("Failed to inject ObjectB");
}
this.objectB.someOtherMethod();
}
}
No need for PowerMock at this point. Mockito can do all the work.
public class ObjectATest
{
#Mock
private ObjectB objectB;
#InjectMocks
private ObjectA objectA;
#Before
public void setup()
{
MockitoAnnotations.initMocks(this);
}
#Test
public void test()
{
try
{
objectA.someMethod();
}
catch(IllegalStateException e)
{
Assert.fail();
}
}
}
You can use the Whitebox class. For example let's say you've created a mock of ObjectB called objectBMock and an instance of ObjectA called objectA:
Whitebox.setInternalState(objectA, objectBMock);
This will "inject" objectBMock to objectA.

Resources