Suppose I have a method like this
String getString()
I can vary easily stub that so that it return "test-string"
def myStub = Stub(MyClass)
myStub.getString() >> "test-string"
Suppose, getString() is within a for loop. And in the loop I'd like it to return "test-string-1" the first time, "test-string-2" the second time, "test-string-3" the third time.
How would I do that?
You can either use the >>> notation in order to chain a fixed series of stub return values or use a closure if you want something more fancy/dynamic:
package de.scrum_master.stackoverflow.q62974132
import spock.lang.Specification
class StubWithMultipleReturnValuesTest extends Specification {
def "stub returns a fixed sequence of values"() {
given:
def underTest = Stub(UnderTest)
underTest.getString() >>> ["test-string-1", "test-string-2", "test-string-3"]
expect:
underTest.getString() == "test-string-1"
underTest.getString() == "test-string-2"
underTest.getString() == "test-string-3"
// As of now, always the last value is returned because
// there are no more new ones in the stub definition
underTest.getString() == "test-string-3"
}
def "stub calculates return value in a closure"() {
given:
def underTest = Stub(UnderTest)
int counter = 0
underTest.getString() >> { "test-string-${++counter}" }
expect:
underTest.getString() == "test-string-1"
underTest.getString() == "test-string-2"
underTest.getString() == "test-string-3"
underTest.getString() == "test-string-4"
}
static class UnderTest {
String getString() {
"real result"
}
}
}
Related
I've just started exploring Dart language and I wanted to test an existing code that I wrote in Java as given:
public interface Condition {
Condition FALSE = facts->false;
Boolean evaluate(Fact<?> fact);
default Condition and(Condition other) {
return fact-> this.evaluate(fact) && other.evaluate(fact);
}
default Condition or(Condition other) {
return fact-> this.evaluate(fact) || other.evaluate(fact);
}
}
And the caller calls it as:
#Test
public void testCondition() {
String str = "A String";
Condition a = fact -> !str.isBlank();
Condition b = fact -> str.contains("A");
a.and(b);
}
A complete test class that makes use of this is :
public class AnonymousLoopTest {
#Test
public void test() {
RulesEngine rulesEngine = new InferenceRuleEngine();
List<Name> names = NamesFactory.fetchNames();
Rules rules = new Rules();
Facts facts = new Facts();
AtomicReference<Integer> countRef = new AtomicReference<>(1);
names.forEach(personName -> {
facts.put("name-" + countRef.get(), personName);
countRef.set(countRef.get()+1);
Condition condition = fact -> !personName.name().isEmpty();
//Hack the comparator logic of DefaultRule/BasicRule in order to override its internal logic as below.
//This is needed to register our Rule with Rules which uses a Set<Rule> to register new Rules
//with the comparator logic written in BasicRule.
Rule nameRule = new RuleBuilder((o1, o2) -> personName.name().compareTo(o1.getName()))
.when(condition).then(action -> System.out.println("In Action:" + personName)).build();
rules.register(nameRule);
});
rulesEngine.fire(rules, facts);
}
}
record Name(Integer id, String name){}
class NamesFactory{
static List<Name> fetchNames(){
return List.of(new Name(10, "Sara"), new Name(20, "Zara"), new Name(30, ""),new Name(40, "Lara"));
}
}
The condition is used by when() method.
In the given example the blank name will be filtered out. The other three names will be printed.
I was trying to write and equivalent in Dart but I'm just stuck. What is the way to write this code in Dart?
That looks like something I'd do by:
typedef Condition = bool Function(Fact);
bool falseCondition(Fact _) => false;
extension ConditionComposition on Condition {
Condition operator &(Condition other) => (Fact fact) => this(fact) && other(fact);
Condition operator |(Condition other) => (Fact fact) => this(fact) || other(fact);
Condition operator ~() => (Fact fact) => !this(fact);
}
If you insist on having a wrapper class for the function objects, I'd do it as:
class Condition {
static const Condition falseCondition = Condition(_kFalse);
final bool Function(Fact) _test;
const Condition(bool test(Fact fact)) : _test = test;
bool evaluate(Fact fact) => _test(fact);
Condition operator &(Condition other) => Condition((fact) =>
this.evaluate(fact) && other.evaluate(fact));
Condition operator |(Condition other) => Condition((fact) =>
this.evaluate(fact) || other.evaluate(fact));
static bool _kFalse(_) => false;
}
but a class seems overkill for something which really is just a simple function. Dart has first class functions.
You can use the former version as:
test("test Condition", () {
var str = "A String";
Condition a = (fact) => str.isNotEmpty();
Condition b = (fact) => str.contains("A");
var both = a & b;
expect(both(someDefaultFact), true);
}
In Javascript when I want to end a function I usually write return, but in the dart, if I do that then the function asks for a return statement at the end of each branch which is messy.
Function createCategory(File image) {
String title = _categoryTitle.value;
if(image == null || title == null || title.length == 0) {
return null;
}
CategoryModel newCategory = new CategoryModel();
if(_categories.value == null) {
_categories.sink.add([newCategory]);
}
return null;
}
What is the correct way to do this in dart?
I think your confusion comes from that your method is valid Dart code but does not really do what I guess you think. Your method has the following signature:
Function createCategory(File image) {
This means your method is named createCategory, takes one argument of the type File and returns a Function. Since you have marked the method to return a Function, then Dart will tell you it is a problem if you just return; since this is properly not what you wanted.
If your method is not going to return any value, then you want to mark this with the return type of void like:
void createCategory(File image) {
String title = _categoryTitle.value;
if (image == null || title == null || title.length == 0) {
return;
}
CategoryModel newCategory = new CategoryModel();
if (_categories.value == null) {
_categories.sink.add([newCategory]);
}
return;
}
I should note, that the last return can be skipped since Dart will automatically add return; at the end of a function if it is missing.
you can do that like this:
void createCategory(File image) {
String title = _categoryTitle.value;
if (image != null && title.isNotEmpty && _categories.value == null) {
_categories.sink.add([CategoryModel()]);
}
}
I am trying to write unit test for addition of 2 numbers which is calling Service class add method() and there is one more class HelperAdd which is called from add() method
Here in unit test case my expected result is different from what is hardcoded in unit test class, How to solve this. Am i doing something wrong in code.
Unit Test Class--
class ControllerTest extends Specification {
Service src
HelperAdd hd
def setup() {
hd = Mock()
src = new Service(
hd: hd
)
}
def "Add 2 numbers"() {
AddModel request = new AddModel()
given: "input"
request.setA(2)
request.setB(3)
when:
src.add(request)
then:
1 * hd.add(_) >> 2
expect:"4"
}
}
Service class --
class Service {
#Autowired
HelperAdd hd
#PostMapping(value="/getdocuments")
def add(#RequestBody AddModel request) {
int a = request.a
int b = request.b
int d = hd.add(a)
int c = a+d
return c
}
}
HelperAdd class--
class HelperAdd {
def add(int a)
{
int k = a+4
return k
}
}
Model class --
#Canonical
class AddModel {
int a
int b
}
I do not understand your problem. The test passes. Your test syntax is weird, though. How about this?
def "Add 2 numbers"() {
given: "input"
def request = new AddModel(a: 2, b: 3)
when:
def result = src.add(request)
then:
1 * hd.add(_) >> 2
result == 4
}
I have a service class defined as follows
class MyService {
def otherService;
def performService( ) {
Navigator.navigate( retrieveData, { otherService.doSomething(it) } );
}
def retrieveData = { Integer offset, Integer maxRows
DomainObject.list(offset,maxRows);
}
}
Navigator.navigate( Closure retriever, Closure processor ) {
def offset=0;
def batchsize=100;
while( (data=retriever(offset,batchsize)) ) {
if(data.size()==0) break;
data.each { processor(it) }
offset += data.size();
}
}
In my tests, I would like to mock the retriveData to retrieve mocked objects
#TestFor(MyService)
class MyServiceSpec extends Specification {
def "test retriever"() {
given:
service.otherService = Mock(OtherService);
service.metaClass.retrieveData = { Integer offset, Integer maxRows ->
if(offset==0) return [ Mock(DomainObject), Mock(DomainObject) ]
else return []
}
when:
service.performService();
then:
2 * otherService.doSomething(_);
}
}
It turns out that the test is not picking up the mocked retrieveData, instead it always picks up the MyService.retrieveData closure, wondering what is the right approach to mock a closure method..
Seems that it's because retrieveData is a field, not a method. Can you try:
given:
...
service.retrieveData = { Integer offset, Integer maxRows ->
...
}
I need to perform some initialization when new instances of my domain class are created.
class ActivationToken {
String foo
String bar
}
When I do this I want bar to be initialized by code inside ActivationToken:
def tok = new ActivationToken(foo:'a')
I cannot see how to 'override' the 'constructor' to make this happen. I know in this case I could just add a normal constructor but this is just a simple example.
The map constructor is coming from Groovy - not Grails in this case. I did some experimentation, and this is what I came up with:
class Foo {
String name = "bob"
int num = 0
public Foo() {
this([:])
}
public Foo(Map map) {
map?.each { k, v -> this[k] = v }
name = name.toUpperCase()
}
public String toString() {
"$name=$num"
}
}
assert 'BOB=0' == new Foo().toString()
assert 'JOE=32' == new Foo(name:"joe", num: 32).toString()
Basically, it appears that you'll have to manually override the constructors if you need to process the property after construction.
Alternately, you can override individual setters, which is cleaner and safer in general:
class Foo {
String name = "bob"
int num = 0
public void setName(n) {
name = n.toUpperCase()
}
public String toString() {
"$name=$num"
}
}
assert 'bob=0' == new Foo().toString()
assert 'JOE=32' == new Foo(name:"joe", num: 32).toString()
Note that the default value isn't processed, but that should be OK in most instances.
The solution above is also good for cases where initializing an object from parameters in a web request, for example, where you wish to ignore extraneous values, catching Missing property exceptions.
public Foo(Map map) {
try {
map?.each { k, v -> this[k] = v }
}
catch(Exception e){
}
}