Spock test framework - how to parametrize a #Rule resource? - groovy

I am updating a Spock tests. There are few mocks and a #Rule resource:
AuthTokenService mockAuthTokenService = Mock()
ObjectMapper mockObjectMapper = Mock()
GeneralConfiguration conf = Mock();
def CLA_BASE_URL = "http://some-prefix/";
#Rule
ResourceTestRule resource = ResourceTestRule.builder()
.addResource(new AuthResourceImpl(mockAuthTokenService, mockObjectMapper, conf))
.build()
I need the resource to have different conf for two different tests. So I tried
def 'create auth token with configured URL prefix'() {
setup:
AuthTokenMetaData authTokenMetaData = buildAuthTokenMetaData()
when:
conf.getClaBaseUrl() >> CLA_BASE_URL
...
But that didn't work, because resource is created once.
So I had to add another resource.
GeneralConfiguration conf2 = new GeneralConfiguration().setClaBaseUrl(CLA_BASE_URL);
#Rule
ResourceTestRule resource2 = ResourceTestRule.builder()
.addResource(new AuthResourceImpl(mockAuthTokenService, mockObjectMapper, conf2))
.build()
But that feels a bit weird, and from brief encounter with Spock, I believe it has some better approach to this.
How can I parametrize the ResourceTestRule?
It has to be a JUnit Rule because of the underlying implementation of ResourceTestRule.

Spock does not provide any mechanism to parametrize a #Rule, as the rule is created before the data driven features are executed.

As Leonard has mentioned, Spock is just a JUnit, it supports #Rule mechanism in the same sense as JUnit, as as such there is no special syntax for this.
So if you need two different configurations, you should probably use two different rules definitions and depending on "groovy-ness" of the test come up with a solution that works for you best:
Here is one example:
class FirstConfigurationSpecification extends Specification {
#Rule // config A
}
class SecondConfigurationSpecification extends Specification {
#Rule // config B
}
// in tests
class MyTestThatRequiresConfigurationA extends FirstConfigurationSpecification {}
// in tests
class MyTestThatRequiresConfigurationB extends SecondConfigurationSpecification {}

Related

Mockito how can simule record doesn't exist

.exception.INSSTaxNotFoundException: INSS Tax not found with ID 1
Could someone help me?
I want mokite "inssTaxService.findById", I don't know how do.
I get this error: INSSTaxNotFoundException: INSS Tax not found with ID 1.
But I could like found the record and go on.
Can I do that in Service or Not?
#Test
void whenINSSTaxIdInformedThenReturnThisINSSTax() throws INSSTaxNotFoundException {
INSSTaxDTO expectedSavedInssTaxDTO = INSSTaxBuilder.builder().build().toINSSTaxDTO();
INSSTax expectedSavedInssTax = inssTaxMapper.toModel(expectedSavedInssTaxDTO);
when(inssTaxService.findById(expectedSavedInssTaxDTO.getId())).
thenReturn(expectedSavedInssTaxDTO);
assertEquals(expectedSavedInssTax.getId(), expectedSavedInssTaxDTO.getId());
assertEquals(expectedSavedInssTax.getDescription(), expectedSavedInssTaxDTO.getDescription());
assertEquals(expectedSavedInssTax.getSocialSecurityRatePercent(), expectedSavedInssTaxDTO.getSocialSecurityRatePercent());
}
What you might be missing is actually injecting the mock of inssTaxService inside your class which you are testing,
Your code would be something like this. Considering its a pure java code(not spring boot etc, you can change the code accordingly in that case).
Mock the service(Which i feel you have done else Mockito would have thrown and error)
InssTaxService mockedInssTaxService = Mockito.mock(InssTaxService.class);
//other impl on this mock for this e.g
when(mockedInssTaxService.findById(expectedSavedInssTaxDTO.getId())).
thenReturn(expectedSavedInssTaxDTO);
Inject the mocked object to the ClassToTest.
ClassToTest classToTest = new ClassToTest(mockedInssTaxService);
If you are using spring boot test you can use #MockBean or #Mock and #InjectMocks instead of new keyword

Micronaut testing - disable cache

Is there possible method to programmatically shut down caches? I tried inject DefaultCacheConfiguration in test class and set inside setup method set testMode=true and maximumSize=0, but still not working.
#MicronautTest
class CategoriesServiceTest extends Specification {
#Inject
#Shared
DefaultCacheConfiguration cacheConfiguration
def setupSpec() {
cacheConfiguration.setMaximumSize(0)
cacheConfiguration.setTestMode(true)
}
}
I found little hack. I'm not sure that is the best solution, but works.
I created class, which globaly shutdown caching for tests:
#Factory
class TestConfig {
#EachBean(DefaultCacheConfiguration)
CacheConfiguration cacheConfiguration(DefaultCacheConfiguration configuration) {
println "disabling cache ${configuration.cacheName}"
configuration.maximumSize = 0
return configuration
}
}
Starting in 1.3.0.M1 a noop cache implementation was added that you can enable for tests or any other environment. See https://micronaut-projects.github.io/micronaut-cache/latest/guide/#noop

Defining Spock mock behaviors

I am writing my first Spock test and read the docs on mocking interactions, but am still not seeing the "forest through the trees" on a few items.
I have a class, MyRealm, that performs authentication for my app. It has two dependencies, AuthService and ShiroAdapter. The former I'd like to mock and the latter I want to leave as-is (if at all possible). This is because the AuthService actually makes a backend connection to LDAP, so I want to mock it. But the ShiroAdapter just defines several utility methods that convert my objects into Apache Shiro security objects (principals, permissions, etc.). So it can be left un-mocked (methinks).
class MyRealmSpec extends Specification {
MyRealm realm
def setup() {
AuthService authService = Mock(AuthService)
// configure 'authService' mock <-- ?????
ShiroAdapter shiroAdapter = new ShiroAdapter()
realm = new MyRealm(authService: authService,
shiroAdapter: shiroAdapter)
}
def "authenticate throws ShiroException whenever auth fails"() {
when:
realm.authenticate('invalid_username', 'invalid_password')
then:
Throwable throwable = thrown()
ShiroException.isAssignableFrom(throwable)
}
}
I believe I'm very close, but am struggling to configure the mock to behave the way I want it to for the test. The Spock docs (linked above) only seem to document how to verify the number of times a mock method is called. I'm not interested in that here.
Here, MyRealm#authenticate(String,String) calls AuthService#doAuth(String,String) under the hood. So I need my mock AuthService instance to simply either return false (indicating failed auth) or to throw an ServiceFaulException if something unexpected happened.
Any ideas how I can accomplish this?
You are very close, an easy, short-hand way to check a thrown exception type is to put the Exception class in parenthesis. Ex:
def "authenticate throws ShiroException whenever auth fails"() {
when:
realm.authenticate('invalid_username', 'invalid_password')
then:
thrown(ShiroException)
}
You also need to mock the LDAP service call itself and simulate an exception or a failed login. The mock operations go in the then clause of your test.
def "authenticate throws ShiroException whenever auth fails"() {
setup:
String invalidUserName = 'invalid_username'
String invalidPassword = 'invalid_password'
when:
realm.authenticate(invalidUserName, invalidPassword)
then:
1 * authService.doAuth(invalidUserName, invalidPassword) >> returnClosure
thrown(ShiroException)
where:
returnClosure << [{throw new ShiroException()}, { false }]
}
Note that you will need to have the arguments on the mock statements match or use wild card matching.
To match on any String you can use the underscore syntax:
1 * authService.doAuth(_, _) >> false
There are a few different behavior objects you might be interested in.
Stub - You only define what gets returned
MyObject obj = Stub{method >> null}
Mocks - You define what gets returned and/or how many times a method is called
MyObject obj = Mock {1..3 methodCall >> false}
Spies - It creates your object but you can override specific methods as a mock (and your overrides can still make calls to the original code)
MyObject obj = Spy {methodCall >> false}
obj.otherMethodCall() // Calls code like normal
obj.methodCall() // Returns false like we told it to
It sounds like you need a stub, but you could use a mock without any issue. I mention spy, because it's a life-saver if your object ever is self dependent (in the future).
def "authenticate throws ShiroException whenever auth fails"() {
given:
AuthService authService = Stub(AuthService)
authService.doAuth(_,_) >> expectedError
MyRealm realm = new MyRealm(
authService: authService,
shiroAdapter: new ShiroAdapter())
when:
realm.authenticate("just enough to get", "to the doAuth method")
then:
thrown(ShiroException)
where:
expectedError << [ShiroException, /*other exceptions this method has to test*/]
}
The data/logic separation isn't needed, but it's a good approach for making tests more flexible and maintainable. Although in this case it's not really needed since you only have one exception to throw.
I would actually separate your failed authentication and exception-ed authentication tests. They're looking at fundamentally different behaviors and the test logic to test both situations is somewhat different. In the interest of maintainability/flexibility, it's in your interest to avoid testing too much (or too little) with each test.
def "authenticate throws ShiroException whenever auth fails"() {
given:
AuthService authService = Stub(AuthService)
authService.doAuth(_,_) >> { args ->
return args[0] == good && args[1] == good
}
MyRealm realm = new MyRealm(
authService: authService,
shiroAdapter: new ShiroAdapter())
expect:
realm.authenticate(username, password) == expectedAuthentication
where:
userName | password | expectedAuthentication
bad | good | false
bad | bad | false
good | good | true
}
Note on the above test, this tests...
The mock's computation for a return value (testing the test)
Any code that happens between calling authenticate and doAuth()
Hopefully that's what you intend. If there's nothing in .authenticate()'s logic that could break (it has complexity on par with a getter or setter method), this test is mostly a waste of time. The only way that logic could break is if something went wrong in the JVM (which is completely outside the responsibility of this test), or someone made a change sometime in the future (ok, even under the huge assumption that .authenticate() contains unbreakably basic logic the test has some value). My rambling off-topic point (terribly sorry); make sure to keep the what & why of your tests in mind. It will help you prioritize test cases and while working out the best ways to organize/separate test logic.

how do I configure my testng IReporter to accept parameters

IReporter is an interface that has a single void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) method. I would like to make the behavior of the reporter configurable so I can pass options to it when run on the commandline. The documentation explains how to pass parameters to a reporter on the commandline:
-reporter The extended configuration for a custom report listener. Similar to the -listener option, except that it allows the
configuration of JavaBeans-style properties on the reporter instance.
Example: -reporter
com.test.MyReporter:methodFilter=insert,enableFiltering=true You
can have as many occurences of this option, one for each reporter that
needs to be added.
So it seems I should be able to call testng with -reporter com.my.reporter:key1=value1,key2=value2
but WHERE do I get the values passed in.
I've looked at the XMLReporter provided by testng, and it has a private final XMLReporterConfig config = new XMLReporterConfig(); line, but I can't find out how the config is ever populated.
Magic, that's how it's done :-) It appears it looks for instance variables on your class that implements IReporter with the same name. It does need a stronger type than Object or def though it seems. Here's an example.
class MyReporter implements IReporter {
int foo; //<-- populated when instantiated
#Override
void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
println "foo = ${foo}"
}
}
And then to execute it:
testng ... -reporter 'full.path.to.MyReporter:foo=42'

Grails Spring Security get assigned roles to a method

I would like to have a test that goes through all methods available in a controller and retrieves roles associated with these methods. I understand that it should be a functional test (as opposed to a unit test), but I still do not know how to request the list of roles associated with a method.
Let's say I have this controller:
#Secured("hasAnyRole('ROLE_1')"
class MyController {
def methodA() {}
#Secured("hasAnyRole('ROLE_2')"
def methodB() {}
}
In my test I would like to have something like this:
assertEquals(['ROLE_1'],getRoles(MyController.class, "methodA"))
assertEquals(['ROLE_1', 'ROLE_2'],getRoles(MyController.class, "methodB"))
Any suggestions?
Thanks.
You can do this with the Reflection API. Something like:
Method m = MyController.class.getMethod("methodB");
Annotation[] annos = m.getAnnotations();
But I don't think that's a good validation for your method, since it only ensure that you write the role name correctly. I think it's better you try to call the action and check if the process redirect to denied.
#TestFor(MyController)
class MyControllerTests {
#Test
void shouldRedirectToDenied() {
SpringSecurityUtils.doWithAuth('username') {
controller.methodB()
assert controller.response.redirectedUrl == '/login/denied'
}
}
}
The doWithAuth closure will mock an authentication for the username, so it's the same to say: "do this code as if the username was logged in successfully".
It seems that you will need to use functional tests indeed. See Burt's comment. I'm still think that's not a valid effort create a test only to validate if the method have the annotation.

Resources