In my Grails 1.3.6 app I've written this class
import org.apache.commons.lang.StringUtils
/**
* Implementation that converts a name such as <tt>FOO_BAR</tt> to <tt>fooBar</tt>
*/
#Singleton
class CamelCaseEnumTransformer implements EnumTransformer {
String transformName(Enum e) {
String transformedName = e.name().toLowerCase()
transformedName.replaceAll(/_([a-z])/) {
it[1].toUpperCase()
}
StringUtils.remove(transformedName, '_')
}
}
I've created this test case:
class EnumTransformerTests extends GroovyTestCase {
private static enum TestEnum {
A, FOO, FOO_BAR, FOO_BAR_123,
}
void testCamelCaseTransformer() {
EnumTransformer transformer = CamelCaseEnumTransformer.instance
assertEquals 'a', transformer.transformName(TestEnum.A)
assertEquals 'foo', transformer.transformName(TestEnum.FOO)
// This test fails on the line below
assertEquals 'fooBar', transformer.transformName(TestEnum.FOO_BAR)
}
}
The test fails on the line marked above. I reckon the problem must be related to the replaceAll method, because this is the first time that the closure passed as the second argument to this method is executed.
The error I get is:
groovy.lang.MissingMethodException: No signature of method:
CamelCaseEnumTransformer$_transformName_closure1.doCall()
is applicable for argument types: (java.lang.String, java.lang.String) values: [_b, b]
What's particularly strange, is that if I run the equivalent code below in the Groovy console, everything seems to work fine.
#Singleton
class CamelCaseEnumTransformer {
String transformName(Enum e) {
String transformedName = e.name().toLowerCase()
transformedName.replaceAll(/_([a-z])/) {
it[1].toUpperCase()
}
}
}
enum TestEnum {
A, FOO, FOO_BAR, FOO_BAR_123,
}
def transformer = CamelCaseEnumTransformer.instance
assert 'fooBar' == transformer.transformName(TestEnum.FOO_BAR)
From the error message text, it looks like the closure should accept 2 arguments for the 2 matches in your regex. Try the following:
transformedName.replaceAll(/_([a-z])/) { wholeMatch, capturedGroups ->
capturedGroups[0].toUpperCase();
}
Related
With mockito-inline how to test static function (with stubbing other static function), or mock/stub some internal depended class?
Here is the sample:
Having a class Util which internally depending on java.security.MessageDigest
package java.security;
public abstract class MessageDigest extends MessageDigestSpi
... ...
public byte[] digest() {
byte[] result = engineDigest();
return result;
}
}
and the container class has a few static functions to be tested
public class Util {
public static byte[] getStringDigest(#NonNull String text, #NonNull String algorithm, #NonNull String charSet) {
if (text == null) {
return null;
}
MessageDigest messageDigest; //<== depend on
try {
messageDigest = MessageDigest.getInstance(algorithm);
messageDigest.update(text.getBytes(charSet));
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
return null;
}
return messageDigest.digest();
}
public static String generateId(#NonNull String s) {
byte[] sha1Byte = getStringDigest(s, "SHA-1", "UTF-8");
if (sha1Byte == null) {
return s;
}
// otherwise build the id
String id = buildId(sha1Byte);
return id;
}
}
would like to test the Utils.generateId(#NonNull String s) with stubbing getStringDigest() returning null, so that sometext is expected to return.
since it is static function so it was tested with powermock.
#Test
public test_util_1{
PowerMockito.mockStatic(MessageDigest.class);
String sometext = "sometext";
PowerMockito.when(Util.getStringDigest(sometext, "SHA-1", "UTF-8")).thenReturn(null);
assertEquals(sometext, Util.generateId(sometext));
}
with mock stub, when Util.getStringDigest() is called null is returned.
It worked fine.
now the mockito-inline supports testing static function (and it has problem to mix with powermockito2 when testing kotlin etc.) so the powermock is removed.
Tried with mockito-inline 3.8.0
#Test
public void test_util_1() {
String sometext = "sometext";
try (MockedStatic<Util> utilMoc = Mockito.mockStatic(Util.class)) {
utilMoc.when(() -> Util.getStringDigest(sometext, "SHA-1", "UTF-8"))
.thenReturn(null);
assertEquals(sometext, Util.generateId(sometext));
}
got error:
java.lang.AssertionError: Unexpected value
Expected :sometext
Actual :null
the Util.generateId(sometext) returns null (not the sometext).
when using assertEquals(sometext, sutilMoc.generateId(sometext)); it cannt compile and says cannt resolve the generateId().
How to use mockito-inline to test the static function?
Or if there is way to mock/stub the depended abstract class MessageDigest for stub the digest() to return null, but dont know is it possible?
found a way to make the test work (using .thenCallRealMethod()),
but still not find a way to mock the depended class which is instantiated inside the static function. if anyone knows a solution for that?
#Test
public void test_util_1() {
String sometext = "sometext";
try (MockedStatic<Util> utilMoc = Mockito.mockStatic(Util.class)) {
utilMoc.when(() -> Util.getStringDigest(anyString(), anyString(), anyString()))
.thenReturn(null);
// need to tell mock to call the original, otherwise a default mocked stub will be called
utilMoc.when(() -> Util.generateId(anyString()))
.thenCallRealMethod();
assertEquals(sometext, Util.generateId(sometext));
}
I am trying to test a method that does an invocation with a closure, something like this:
def foo(Long param) {
AnObject.doSomething {
bar(param)
}
}
And I want to test that doSomething is called with a closure that calls bar with the expected value inside.
I'm able to test properly the doSomething invocation by creating a spy and doing
when:
service.foo(1L)
then:
1 * AnObject.doSomething{_}
However, I cannot seem to find a way to perform assertions on the contents of the closure.
What's the appropriate way to assert that inside the closure bar gets called with 1L?
Without seeing more of your code, I think you would need to spy on the class providing the bar method. This is a bit contrived because the test is supplying the closure, but I think it is something like this:
import spock.lang.Specification
class Bar {
void bar(def param) {
println param
}
}
class DoSomethingTestSpec extends Specification {
class AnObject {
void doSomething(Closure c) {
def param = 1L
c.call(param)
}
}
def "test AnObject doSomething calls the closure"() {
given:
def closure = { def p ->
Bar.bar(p)
}
and:
GroovySpy(Bar, global:true)
and:
AnObject anObject = new AnObject()
when:
anObject.doSomething(closure)
then:
1 * Bar.bar(_) >> { args ->
assert args[0] == 1L
}
}
}
I am using JDBI 3 and have written the following utility function.
public class JdbiHelper {
// ...
public <T, DAO> T fetch(final Function<DAO, T> function, Class<DAO> daoClass) {
return dbi.withHandle(handle -> {
final DAO dao = handle.attach(daoClass);
try {
return function.apply(dao);
}
finally {
handle.close();
}
});
}
}
which I can call in methods like this
public Optional<Account> findByEmailAddress(final String emailAddress) {
if (!exists(emailAddress))
return Optional.empty();
return jdbiHelper.fetch(dao -> ofNullable(dao.selectByEmailAddress(emailAddress)), AccountDAO.class);
}
private boolean exists(final String emailAddress) {
return jdbiHelper.fetch(dao -> dao.count(emailAddress) > 0, AccountDAO.class);
}
I am trying to write a test for the findByEmailAddress mocking jdbiHelper using Mockito 2 but cannot work out how to mock the dao -> part of the method.
I've tried using jdbiHelper.fetch(any(Function.class), eq(AccountDAO.class)) but as there are two different expectations of what to return it fails trying to cast one or the other.
Passing in a mocked Function causes a NPE as the dao param is null.
I have this Java test with Mockito:
public class PersistentNodeDeserializerTests {
#Test
public void userInfoPersistentNodeDeserializer() {
PersistentNode node = mock(PersistentNode.class);
when(node.stringChild("username")).thenReturn("cliff12");
//more stuff
}
}
PersistentNode is a Kotlin class:
open class PersistentNode(private val path: PersistentNodePath, val content: Any) {
val stringPath: String
get() = path.get()
val key: String
get() {
val parts = stringPath.split("/");
return parts[parts.size - 1];
}
val mapContent: Map<String, Any>
get() {
return content as HashMap<String, Any>
}
fun stringChild(child: String): String {
return mapContent.get(child) as String
}
}
I get this error:
kotlin.TypeCastException: null cannot be cast to non-null type
java.util.HashMap
How can I mock the property stringChild properly?
this library may solve your issue https://github.com/nhaarman/mockito-kotlin
EDIT: sorry, didn't realize you were using a Java test. If it's an option, try writing your test in kotlin too
I'm trying to write a unit test for a method which has takes in a .class parameter.
For example:
ExampleService {
def myExample(clazz){
//do stuff and return some object
}
}
/* How the above function gets used */
AnotherExampleService extends exampleService {
def blah() {
def obj = myExample(AnotherClass.class)
}
}
/* Now I need to test the above blah() function */
AnotherExampleServiceSpec extends Specification {
def "test blah"() {
//The following doesn't seem to work
ExampleService.metaClass.myExample = { def arg1 -> obj }
}
}
I'm pretty new to Groovy/Grails, so any help would be much appreciated. I basically want to know why my unit test doesn't seem to work, and how to test such a function that takes in a paramter of a class instance.
Thank you for your help!
I would probably subclass the ExampleService in the test. So it looked like:
ExampleService {
def myExample(clazz){
//do stuff and return some object
}
}
AnotherExampleService extends ExampleService {
def exampleService
def blah() {
def obj = myExample(AnotherClass)
}
}
AnotherExampleServiceSpec extends Specification {
def "test blah"() {
given:
AnotherExampleService service = new AnotherExampleService() {
#Override
def myExample(clazz){
//whatever you want to do
return whatEverResult
}
when:
def result = service.blah (SomeClass)
then:
result
}
}
As you can see the myExample methods is overridden here to return some mock value and there's no tinkering with metaclass :-) To make it easier for Groovy you can explicitly state the input type e.g. def myExample(Class clazz).