In a unit test, I have created mock for the function ExecuteDeleteQuery
ExecuteDeleteQuery = func(deleteQuery string) ([]string, error) {
return nil,nil
}
How can I capture the argument passed to this function and assert that?
I want to do something like:
assertEqual(t, deleteQuery, expectedDeleteQuery)
If you just need to capture one value, you can do something like this:
var gotDeleteQuery string
ExecuteDeleteQuery = func(deleteQuery string) ([]string, error) {
gotDeleteQuery = deleteQuery
return nil,nil
}
// ...
assertEqual(t, gotDeleteQuery, expectedDeleteQuery)
Related
I have the following code. Dictionary is just a wrapper for a List of type String.
public Dictionary getDictionary(int size, String text) {
return restTemplate.execute(url, HttpMethod.GET, null, response -> {
BufferedReader br = new BufferedReader(new InputStreamReader(response.getBody()));
List<String> words = new ArrayList<>();
String line;
while((line = br.readLine()) != null){
if (isMatch(line, size, text)){
words.add(line.toLowerCase());
}
}
br.close();
return new Dictionary(words);
});
}
private boolean isMatch(String word, int size, String text) {
if(word.length() != size) {
return false;
}
return wordUtil.isAnagram(word, text);
}
I'm having a hard time test this method at the moment. The HTTP call just returns a list of words in plain text with new line separators.
I want to write a test where I can stub the response.getBody().
I.e. I want response.getBody() to return a bunch of words, and I'll assert that the returned Dictionary only contains the words that are of size size and that are an anagram of the string text.
Is this possible?
Thanks
It is possible to stub a method taking a callback, and execute the callback when the stub is called.
The idea is to:
use when / thenAnswer to execute code when the stubbed method is called
use invocationOnMock passed to thenAnswer to get the callback instance
call the callback, providing necessary params
#Test
void testExecute() {
String responseBody = "line1\nline2";
InputStream responseBodyStream = new ByteArrayInputStream(responseBody.getBytes());
ClientHttpResponse httpResponse = new MockClientHttpResponse(responseBodyStream, 200);
when(restTemplate.execute(any(URI.class), eq(HttpMethod.GET), eq(null), any())).thenAnswer(
invocationOnMock -> {
ResponseExtractor<MyDictionary> responseExtractor = invocationOnMock.getArgument(3);
return responseExtractor.extractData(httpResponse);
}
);
MyDictionary ret = aController.getDictionary(1, "text");
// assert ret against your expecations
}
Having said that, this seems to be a bit complicated for the task at hand. IMHO you will be better off if you separate the logic of dealing with Http from your business logic. Extract a method taking your inputStream, and test that separately.
I have some static method:
class WebUtils {
static httpPostRequest(String url, Map data, Map headers) {
//some code here
}
}
And service:
class ChatService {
void sendMessage(String text) {
//some preparing code
WebUtils.httpPostRequest(url, data, headers)
}
}
Now I want to check invocation of static method in the service by unit-test. Somehow like this:
void "test sending message"() {
given:
String text = 'Test'
def mockedWebUtils = Mock(WebUtils)
when:
service.sendMessage(message)
then:
1*mockedWebUtils.httpPostRequest(_, [text: message], _)
}
But code above is not working. Is there legal way?
Try something like:
void "test sending message"() {
given:
WebUtils.metaClass.static.httpPostRequest = { String url, Map data, Map headers ->
return 'done' // you can do what you want here, just returning a string as example
}
when:
service.sendMessage( 'Test' )
then:
1
// test for something your method has done
}
The correct way is using GroovyMock instead Mock:
void "test sending message"() {
given:
String text = 'Test'
GroovyMock(global:true, WebUtils)
when:
service.sendMessage(text)
then:
1*WebUtils.httpPostRequest(_, [text: text], _)
}
I've found here:http://spockframework.org/spock/docs/1.3-RC1/interaction_based_testing.html#_mocking_static_methods
I have some code on the follwing form:
#Language("SQL")
val someSql = """
SELECT foo
FROM bar
WHERE foo = :foo
"""
return session.select(some, mapOf("foo" to foo)) {
MyObject(
foo = it.string("foo"),
)
}.firstOrNull()
which use the below from com.github.andrewoma.kwery.core. Note the lambda in the method signature:
fun <R> select(#Language("SQL") sql: String,
parameters: Map<String, Any?> = mapOf(),
options: StatementOptions = defaultOptions,
mapper: (Row) -> R): List<R>
I use mockitokotlin2.
I need to return an instance of MyObject when the session select method is called with a select query (containing "SELECT foo").
I was thinking I could pass a mock into the lambda as below (but then it wont match the method call I am trying to mock). The below code is an attempt. But it never matches in eq(function2):
val function2: (Row) -> Int = mock {
onGeneric { invoke(any()) }.thenReturn(MyObject(foo="test-foo"))
}
val session = mock<Session> {
on { select(sql = any(), parameters = any(), options = any(), mapper = eq(function2))}.thenReturn(listOf(MyObject(foo="test-foo")))
}
function2 in my case is not really a mapper, it is not eq to what I am trying to mock, it never matches and the mock is never called.
So what do I put in the mock of session, select instead of eq(function2) in the code above to get MyObject object returned?
I think you just need to specify they type that your mapper is expected to return when setting up the session mock - in your case looks to be Function1<Row, MyObject>
val session = mock<Session> {
on { select(sql = anyString(), parameters = anyMap(), options = any(), mapper = any<Function1<Row, MyObject>>())}.thenReturn(listOf(MyObject(foo="test-foo")))
}
I need to create JSON data using few keys of map and need to incorporate into html generated. I am using pongo2 library and want to write custom filter to achieve the same.
<script> {{ CategoryMapping|MycustomFilter }} </script>
and coded custom filter like below.
func init() {
pongo2.RegisterFilter("superfilter", GetCategoryJsonData)
}
func GetCategoryJsonData(CatAttributeMapping *map[string]interface{}, param *int) (*string, *error) {
.....
}
But I am getting below error.
src/util/TemplateFilters.go:10: cannot use GetCategoryJsonData (type func(*int, *int) (*string, *error)) as type pongo2.FilterFunction in argument to pongo2.RegisterFilter
I am following below documentation - https://godoc.org/github.com/flosch/pongo2#FilterFunction
I am new to go and unable to understand what wrong I am doing here. Please guide me for the same.
The problem is that your filter function does not accept or return the right types to match what pongo2 is requiring. Let's walk through the docs and see what they want.
First, take a look at the godoc for RegisterFilterFunction. It says
func RegisterFilter(name string, fn FilterFunction)
This is in the pongo2 package so you should read this as RegisterFilter is a function that accepts two arguments and returns no values. The first argument name is of the builtin type string and the second argument fn is of the type pongo2.FilterFunction. But what is a pongo2.FilterFunction? Well clicking on it we see further down in the doc
type FilterFunction func(in *Value, param *Value) (out *Value, err *Error)
In Go you can make your own types based on any other types including functions. So what pongo2 has done is to create a named type called FilterFunction that is any func which accepts two arguments (both of type *pongo2.Value) and returns two values (one of type *pongo2.value and one of type *pongo2.Error).
To bring it all together we would do something like this:
package main
import (
"fmt"
"log"
"strings"
"github.com/flosch/pongo2"
)
func init() {
pongo2.RegisterFilter("scream", Scream)
}
// Scream is a silly example of a filter function that upper cases strings
func Scream(in *pongo2.Value, param *pongo2.Value) (out *pongo2.Value, err *pongo2.Error) {
if !in.IsString() {
return nil, &pongo2.Error{
ErrorMsg: "only strings should be sent to the scream filter",
}
}
s := in.String()
s = strings.ToUpper(s)
return pongo2.AsValue(s), nil
}
func main() {
tpl, err := pongo2.FromString("Hello {{ name|scream }}!")
if err != nil {
log.Fatal(err)
}
// Now you can render the template with the given
// pongo2.Context how often you want to.
out, err := tpl.Execute(pongo2.Context{"name": "stack overflow"})
if err != nil {
log.Fatal(err)
}
fmt.Println(out) // Output: Hello STACK OVERFLOW!
}
I'm writing a unit test which tests the scenario where a body is sent in the request which is a plain string, i.e. not parseable as JSON.
In this test, I'm setting the HttpRequestMessage something like this:
var ojectContent = new ObjectContent(typeof(string)
, "aaaaa"
, new JsonMediaTypeFormatter());
httpRequestMessage.Content = objectContent;
The problem is, when I debug the code, the request body has been set to "aaaaa" (note the additional quotes) which is enough to cause the deserialisation code to treat the request body differently, meaning I can't test what I mean to test. I need the request body to be aaaaa.
Can anyone advise how I can set up the test so that the request body does not contain these quotes?
Edit: I have also tried new ObjectContent(typeof(object)... and it gives the same result.
Another way is to bypass the MediaTypeFormatter by using StringContent instead of ObjectContent:
var content = new StringContent("aaaaa");
httpRequestMessage.Content = content;
Okay, so I needed to create a media type formatter that didn't interfere with the input in any way. I used this:
private class DoNothingTypeFormatter : MediaTypeFormatter
{
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
if (type == typeof(string))
{
return true;
}
return false;
}
public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, HttpContent content, TransportContext transportContext)
{
var myString = value as string;
if (myString == null)
{
throw new Exception("Everything is supposed to be a string here.");
}
var length = myString.Length;
var bytes = System.Text.Encoding.UTF8.GetBytes(myString);
return Task.Factory.StartNew(() => writeStream.Write(bytes, 0, length));
}
}
Then, when I want to generate the body of the `HttpRequestMessage', I do so like this:
objectContent = new ObjectContent(typeof(string)
, "not json"
, new DoNothingTypeFormatter());