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).
Related
FuncRes Test::test(HttpRequest& request, std::string& result) {
try {
auto httpClientSync = HttpClientSync::create(param);
HttpResponse response = httpClientSync->execute(request);
if (...) {
return FuncRes::SUCCESS;
} else if (...) {
return FuncRes::RETRY;
} else {
return FuncRes::FAILED;
}
} catch (...) {
return FuncRes::RETRY;
} catch (...) {
return FuncRes::FAILED;
}
}
httpClientSync is a local variable, it will destroy when the test is done.
I'm confused if I can mock HttpClientSync and "execute" method?
Refactor this function into 2 parts, one that creates real HttpClientSync, and one that accepts HttpClientSync interface:
FuncRes Test::test(HttpClientSync& httpClientSync, HttpRequest& request, std::string& result);
FuncRes Test::test(HttpRequest& request, std::string& result) {
auto httpClientSync = HttpClientSync::create(param);
test(httpClientSync, request, result);
}
Then test variant which accepts HttpClientSync in arguments, and pass mock instead of real client.
If you need to test some other code which calls this test function, and you still want to mock HttpClientSync, then instead of storing param in your Test class, store HttpClientSync& client instance, and pass it in constructor.
I'm trying to mock twilio module but it's being a pain. I'm new to Jest and I've read docs but it's not clear how should I mock a class and a type.
This is the code that I'm trying to mock:
const Twilio = require('twilio')
const client = new Twilio('sid', 'auth')
const response = new Twilio.twiml.VoiceResponse()
The part of constructor new Twilio is doing fine:
jest.mock('twilio', () => class {
constructor (accountSid, authToken) {
this.conferences = {
list () {
return mockTwilioListConferences()
}
}
}
})
But how can I mock the part new Twilio.twiml.VoiceResponse()?
Twilio developer evangelist here.
Disclaimer, I haven't tried this, but here's how I believe this works.
The twiml property on the Twilio class is just that, a property. In your mock you instantly return a new anonymous class, but if you add the property to the class itself before you return you should find it is then part of your mock.
For example:
jest.mock('twilio', () => {
const mockClass = class {
constructor (accountSid, authToken) {
this.conferences = {
list () {
return mockTwilioListConferences()
}
}
}
}
mockClass.twiml = {
// complete your mock implementation here
}
return mockClass;
);
Let me know if that helps at all.
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.
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();
}