So assuming we're trying to unit test a controller that uses criteria methods or named queries on a domain class how can we enhance the capabilities of mockDomain? One of my favourite Groovy libraries is GMock which I use in preference to Groovy's built in mock capabilities. One of its really powerful features is the ability to use 'partial mocks', i.e. to mock particular methods on a class whilst allowing the rest of the class to continue functioning as normal. This means we can layer a mocked createCriteria, withCriteria or named query call on to a domain class that is already enhanced by mockDomain.
First off you need to add the GMock dependency to your BuildConfig.groovy. Since GMock supports Hamcrest matchers for matching method arguments you'll probably want those as well:
dependencies { test "org.gmock:gmock:0.8.0" test "org.hamcrest:hamcrest-all:1.0" }If you're using an earlier version of Grails you'll need to just grab the jar files and put them in your app's lib directory.
Then in your test case you need to import GMock and Hamcrest classes and add an annotation to allow GMock to work:
import grails.test.* import org.gmock.* import static org.hamcrest.Matchers.* @WithGMock class MyControllerTests extends ControllerUnitTestCase {
Adding criteria and named query methods is now fairly simple:
Mocking a withCriteria method
def results = // whatever you want your criteria query to return mock(MyDomain).static.withCriteria(instanceOf(Closure)).returns(results) play { controller.myAction() }Breaking this example down a little
mock(MyDomain)
establishes a partial mock of the domain class.instanceOf(Closure)
uses a Hamcrest instanceOf matcher to assert that the withCriteria method is called with a single Closure argument (the bit with all the criteria in).returns(results)
tells the mock to return the specified results which here would be a list of domain object instances.
Mocking a createCriteria method
The withCriteria method returns results directly but createCriteria is a little more complicated in that it returns a criteria object that has methods such as list, count and get. To simulate this we'll need to have the mocked createCriteria method return a mocked criteria object.def results = // whatever you want your criteria query to return def mockCriteria = mock() { list(instanceOf(Closure)).returns(results) } mock(MyDomain).static.createCriteria().returns(mockCriteria) play { controller.myAction() }This is only a little more complex than the previous example in that it has the mocked list method on another mock object that is returned by the domain class' createCriteria method.
mock()
provides an un-typed mock object as we really don't care about the type here.Mocking a named query
For our purposes named queries are actually pretty similar to createCriteria.def results = // whatever you want your criteria query to return def mockCriteria = mock() { list(instanceOf(Closure)).returns(results) } mock(MyDomain).static.myNamedQuery().returns(mockCriteria) play { controller.myAction() }
Some other examples:
Mocking a named query with an argument
mock(MyDomain).static.myNamedQuery("blah").returns(mockCriteria)For simple parameters you don't need to use a Hamcrest matcher - a literal is just fine.
Mocking a withCriteria call using options
You can pass an argument map to withCriteria, e.g.withCriteria(uniqueResult: true) { /* criteria */ }
will return a single instance rather than a List. To mock this you will need to expect the Map as well as the Closure:def result = // a single domain object instance mock(MyDomain).static.withCriteria(uniqueResult: true, instanceOf(Closure)).returns(result)
Mocking criteria that are re-used
It's fairly common in pagination scenarios to call a list and count method on a criteria object. We can just set multiple expectations on the mock criteria object, e.g.def mockCriteria = mock() { list(max: 10).returns(results) count().returns(999) } mock(MyDomain).static.myNamedQuery().returns(mockCriteria)
The nice thing about this technique is that it doesn't interfere with any of the enhancements mockDomain makes to the domain class, so the save, validate, etc. methods will still work as will dynamic finders.
Be aware however, that what we're doing here is mocking out the criteria queries, not testing them! All the interesting stuff inside the criteria closure is being ignored by the mocks and could, of course, be garbage. Named queries are pretty easy to test by having integration test cases for your domain class. Criteria queries beyond a trivial level of complexity should really be encapsulated in service methods or named queries and integration tested there. Of course, GMock then makes an excellent solution for mocking that service method in your controller unit test.
80 comments:
Good to see a blog introducing GMock. :)
Actually, "mock(MyDomain).static..." is called static mocking, and partial mocking is something like "mock(controller)...". Nevertheless, static mocking is also mocking static methods partially, so you can call it "static partial mocking". :)
There is a new feature called chained methods in the incoming GMock 0.9.0 can simplify the mocking the createCriteria(). You can chains the methods like "mock(MyDomain).static.createCriteria().chains().list(...).returns(results)".
What's more, you can also test the closure of withCriteria() in GMock 0.9.0 like:
mock(MyDomain).static.withCriteria(invoke {
between(...)
like(...)
}).returns(results)
Nice, I didn't know about that feature.
Chaining will be really useful as well.
Awesome post Rob, just what I needed!
Rob, I'm trying to follow your examples, mainly with the named queries, but in my case to test the named query itself.
So I have something like (sorry for my spanish coding):
def results = [] << Historico.findByProgramaID('2') << Historico.findByProgramaID('3') << Historico.findByProgramaID('4')
def mockCriteria = mock() {
list(instanceOf(Closure)).returns(results)
}
mock(Historico).static.todosActivos().returns(mockCriteria)
And then when I try to play it, I'm getting an error:
play {
assert results == Historico.todosActivos()
}
Could it be even possible to do something like this?:
play {
def r = Historico.todosActivos()
assert ['2', '3', '4'] == r*.programaID
Thanks in advance.
I think it should be
assert results == Historico.todosActivos().list {...}
Unfortunately I get this error when trying the "Historico.todosActivos().list { ... }:
nexpected method call 'list()' on 'Mock for Object' 'list(an instance of groovy.lang.Closure)' on 'Mock for Object': expected 1, actual 0 'Historico.todosActivos()': expected 1, actual 1
junit.framework.AssertionFailedError: Unexpected method call 'list()' on 'Mock for Object'
'list(an instance of groovy.lang.Closure)' on 'Mock for Object': expected 1, actual 0
'Historico.todosActivos()': expected 1, actual 1
at org.gmock.internal.InternalMockController.fail(InternalMockController.groovy:185)
at org.gmock.internal.InternalMockController$fail.call(Unknown Source)
at org.gmock.internal.metaclass.MetaClassHelper.findExpectation(MetaClassHelper.groovy:25)
at org.gmock.internal.metaclass.MetaClassHelper$findExpectation.callStatic(Unknown Source)
at org.gmock.internal.MockInternal.invokeMockMethod(MockInternal.groovy:80)
at org.gmock.internal.metaclass.MockProxyMetaClass$2.call(MockProxyMetaClass.java:53)
at org.gmock.internal.InternalMockController.doWork(InternalMockController.groovy:218)
at org.gmock.internal.InternalMockController.this$2$doWork(InternalMockController.groovy)
at org.gmock.internal.InternalMockController$this$2$doWork.callCurrent(Unknown Source)
at org.gmock.internal.InternalMockController$this$2$doWork.callCurrent(Unknown Source)
at org.gmock.internal.InternalMockController.doInternal(InternalMockController.groovy:207)
at org.gmock.internal.InternalMockController$doInternal.callCurrent(Unknown Source)
at org.gmock.internal.InternalMockController$doInternal.callCurrent(Unknown Source)
at org.gmock.internal.InternalMockController.doInternal(InternalMockController.groovy:200)
at org.gmock.internal.metaclass.MockProxyMetaClass.invokeMethod(MockProxyMetaClass.java:47)
at org.gmock.internal.metaclass.MockProxyMetaClass.invokeMethod(MockProxyMetaClass.java:43)
at es.cuestamenos.dominio.HistoricoTests$_testTodosActivos_closure2.doCall(HistoricoTests.groovy:83)
at es.cuestamenos.dominio.HistoricoTests$_testTodosActivos_closure2.doCall(HistoricoTests.groovy)
at org.gmock.internal.InternalMockController.play(InternalMockController.groovy:116)
at org.gmock.internal.InternalMockController$play.call(Unknown Source)
at org.gmock.GMockController.play(GMockController.groovy:29)
at org.gmock.GMockController$play.call(Unknown Source)
at es.cuestamenos.dominio.HistoricoTests.play(HistoricoTests.groovy)
at es.cuestamenos.dominio.HistoricoTests.testTodosActivos(HistoricoTests.groovy:82)
Anything else I could try?
I think you should use "list{}" instead of "list()"
That did the trick. I forgot that I defined the mock as list(instanceOf(Closure)) ;-)
Thanks!
Actually, I just realized that this trick is great to simulate the named query, but not to test it, as it will always pass the test, right?
What are your thoughts on this?
Yes, this technique is *not* suitable for testing the query. It's for testing the logic in code that uses the query without having to connect to a real database or set up real test data.
All you're doing in that code is testing the mock you just set up.
Rob, and any idea on how I could test the named query itself meanwhile support for mockDomain is added to Grails?
Thanks for the great example. It was a big help to us starting out with Grails.
If your named query takes parameters, you need to define it a bit differently.
def results=[]
def params
def mockCriteria = mock() {
list().returns( results)
}
mock(Keyword).static.myNamedQuery(params)
.returns(mockCriteria)
Just a remark: mocking static methods using GMock will make tests fall if you or some Grails plugin need to call other static methods on particular class. The fix is to combine GMock with the standard Groovy metaprogramming:
def results = // whatever you want your criteria query to return
def mockCriteria = mock() {
list(instanceOf(Closure)).returns(results)
}
MyDomain.static.createCriteria = { -> mockCriteria}
play {
controller.myAction()
}
Thanks for your sharing! The information your share is very useful to me and many people are looking for them just like me! thank you! I hope you have many useful articles to share with everyone!
slither io
Essentially, an abstract on research paper is an extrapolation of course works written in a report format specified by the professor. Typically, an abstract consist of one paragraph that summarizes the contents of the article in precise terms.
Thanks for providing great information and looking beautiful blog, extremely decent required data and the things I never envisioned and I would ask for, wright more blog and blog entry like that for us Top Gun Jacket
This is the first time that I visit here. I found so many exciting matters in this particular blog, One thing I would like to request you that pls keep posting such type of informative blog. Movie Jackets
https://americanexpresscomconfirmcard.live/ add comments
This blog is very informative thanks for sharing this with us. I appreciate your work. Check out our 100% leather
Top Gun Jacket and also check Film jacket, Gaming jacket, TV series jacket and many more.
Your blog is awesome I got all those things what I want to know. Thanks for sharing. Check out our new famous outfit The Gentlemen Coach Tracksuit
Top quality leather jackets available for our clients from the world of sports featured in the WWE Mens Jackets
I'm glad by reading your fascinating article, also I love this The Genuine Leather, Keep uploading more interesting articles.
Bravo!! what an interesting post. Very interesting information. Visit -> Bearingpk
best post
Playerunknown’s Battlegrounds Leather Jacket
This is the first time that I visit here. I found so many exciting matters in this particular blog, One thing I would like to request you that pls keep posting such type of informative blog. Assassin’s Creed Coat
This is such an amazing resources, that you were giving me the how you looking the part of it. I'm happy to have discovered this post as its such an attractive one! Altered Carbon Coat
I am consistently watchful for quality posts and articles so I think I'm successful to have discovered this! Joaquin Phoenix Coat
Buy this Wool Blend Wes Bentley Grey Jacket SHOP NOW......
Famous Jacket
This website is about leather jackets.
https://superstarjackets.com/product/get-smart-agent-99-anne-hathaway-white-leather-jacket/
Amazing leather jacket for winters.
https://superstarjackets.com/product/gigi-hadid-black-double-rider-genuine-leather-jacket-available-online/
I like this jacket. Thank you so much
https://superstarjackets.com/product/gigi-hadid-black-shearling-leather-jacket-available-online/
Come to our site. www.superstarjackets.com
https://superstarjackets.com/product/gigi-hadid-brown-cropped-leather-jacket/
Wanna buy leather jackets with extreme Quality and same as want ???
https://superstarjackets.com/product/irina-shayk-slim-fit-double-breasted-brown-leather-trench-coat/
We are here to provide you upper class quality in leather Jackets. You can buy any type of celebrity jackets from www.superstarjackets.com
https://superstarjackets.com/product/isla-fisher-leather-jacket/
Superstar Jackets have each celebrity jackets you ever seen on TV shows, movies, and seasons. You can buy from www.superstarjackets.com
https://superstarjackets.com/product/jenna-coleman-doctor-who-clara-oswald-black-biker-leather-jacket/
The BWC is also at an advantageous location because its juxtaposition to the proposed Rawalpindi Ring Road is the nearest compared to all other upcoming housing societies being developed in the area. The 4 unique accesses to BWC is a real estate investor’s hotspot in Islamabad. The future holds the immense potential of fantastic returns on investments in this housing society because of its central location and state-of-the-art infrastructure.
Blue world city Islamabad installment plan
park view lahore payment plan
Rudn Enclave payment plan
Such a very useful article. Very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article. THE LAST OF US PART II JACKETS
Wow such an amazing content I really like it. Here is discounted coupon fr you avail it now from here wanikani promo code
This is an amazing post for all the viewer's thanks for creating it journalist killed in afghanistan.
Hy I'm Designer For Customize Leather Jackets. Please Visit Our Website. Teen Wolf Derek Hale Faux Leather Jacket
Thanks for sharing this amazing blog with some unique information keep it up. Here is my new bloxland promo code
Pakistan insider Hey! Thanks for the info. This info helped me a lot. I will wait some more.
RightJackets is the best place for you to get the most original custom made products and more.We have the biggest range of a variety of products.
Calf Skin Brown Leather Jacket
HUF Reversible Silver Easy Satin Jacket
Casual Purple Motorcycle Leather Jacket
God Created Adam & Eve Not Adam & Steve Jacket
Ladies Brando Green Fitted Suede Leather Jacket
RockStar Jackets is incredibly pleased to announce ourselves as the most dependable manufacturers and exporters of a variety of products comprising of Leather Garments.
Burberry Brit Shearling-trimmed Moto Leather Jacket
Singer Justin Bieber ‘Believe Tour’ at The Valley View Casino Center Leather Jacket
Mackage Fur-trimmed Glen Down Bomber Leather Jacket
Haute Hippie Brown Biker Leather Jacket
Reformation Style Black Leather Jacket
HARDCORE CYCLES was started in the Greater Philadelphia area by a group of tight friends with a passion for V-Twin performance aftermarket parts.Visit our Website Thanks
Feuling LIFTERS 508 RAC CH DRV M8
Shop this best quality Kayce Dutton Yellowstone Brown Jacket For men SHOP NOW
Your article is really addictive. Keep posting. keep sharing the knowledge. I love to read your articles. Thank you for sharing this article with us. This article will make a good reference for me. Thanks a lot. It is appreciated.
Best real estate company in Islamabad
Nice article! It's a great experience for this website. It's really helpful for me. So I have also recommended you come to this site. Take My Online Course
We all face strict deadlines to complete do exam for me Do exams for me provide the best help for your queries like “can I hire someone to do my exam?” to complete your paper just in time our experts are available all day and night.
Anzo Marketing is one of the top real estate marketing companies that deal with top housing projects like NOVA City Islamabad. Customer satisfaction is our top priority.
Cosmetics and beauty products can help our skin in a number of ways. However, because everyone has various skin types, it is up to each person to determine CBD Skin Care Wholesale which product will be their greatest helper. For this reason, we created our cosmetic line, which consists of 5 original formulas and provides a wide range of skin types with several uses, including:
This is quite interesting. I am so glad that you have shared this amazing blog post. I will definitely share this informative blog with my friends and other social sites. Mens Suits
l6e17s0f10 n3e32b3a93 e5s31i1r06 z9s32j7f23 i5k90n4i55 z1w98g3f24
Amazing. Previously I had no idea about this feature.
XNO Sports
It's the right time to change your SEO services agency if your site has failed to generate traffic even after months. Social Ninja is the one online stop shop where you can find the best solutions for your website’s SEO ranking. We pay attention to web development, content marketing, digital marketing, e-commerce, and other services to boost the site's traffic by making it more attractive. We work to retain the clients and not just work with them once. Our company strives to give you a great experience every time with mind-blowing SEO services. Reach us now so that we start a discussion today.
http://socialninjaagency.com/
Fashion is the thing that you make it – The primary thing you need to comprehend about fashion is that it is just what you make it, that’s it. Princess Diana Jacket
quironsalud
https://quironsalud.ae
The finest staff, the most advanced technology, research, training, and a common management model all back the Group's commitment to quality services for all citizens. Quirónsalud covers all medical specialties, providing particularly outstanding service in diagnosis and treatment of cardiovascular disease and cancer.
https://montessorivision.com/products/magical-tracing-workbook
Do you want your children to develop their creativity and imagination while developing problem-solving skills and coordination? Montessori vision can help you with that. Our range includes classic wooden memory blocks, magic tracing workbook, magical drawing book, puzzles, Montessori animals, worm game, Montessori train set, Montessori toys target, and modern digital and basic science kits. Whether they choose to explore with our blocks, instruments, books, art, and activity supplements or spend many hours interacting with our apps and video entertainment built right into some of our most advanced intelligent mirrors yet, your little ones will enjoy an unrivaled experience in proprioception, expressive language development, cognitive enrichment, and physical externality. In short, we teach your children all the different ways to play and learn
People frequently decline to move to various nations due to the hustle of visa application processes, payment, documentation, and settlement in another country. But, DM Consultants give adequate movement administrations to individuals of India to effortlessly go to another state and start a new life by depending on us with all legal procedures. If you are confused, get in touch with us through our site or visit our office in India for good consultancy and direction
https://www.dm-consultant.in/
Such an interesting article here.I was searching for something like that for quite a long time and at last I have found it here. wyatt langmore Jacket
Why Dessert Safari is So Famous
Finding the right kind of blogs for your everyday read could be a hustle, but with Technology Center UAE it is a work of just minutes. We offer you a wide variety of blogs and articles that full fill your likings. With us you will find pieces that will add up a lot to your knowledge. Skim through our website today and find what you like.
https://uaetechcenter.com/
Mrs kapri Loup
Travel Hub
This blog provides a quick guide on everything you need to know before renting a car in Dubai. It covers important topics such as driving requirements, rental fees, insurance, and more. Whether you're a tourist or a resident, this guide can help you make informed decisions when renting a car in Dubai.
https://traveluaehub.com/
Looking for something incredible to read in your daily routine? We heard you! local company 24 is thrilled to bring to you the best kinds of read that can make your everyday knowledge better and wider. With us you will get to read blogs and articles that are easy to read and understand. Visit out website today and find your choice of articles and blogs today.
https://localcompany24.com/
"This blog has a unique ability to spark curiosity and encourage further exploration. The writer introduces fascinating topics and leaves readers with a desire to dive deeper into the subject matter. It's a gateway to endless learning."
Costco Tire Promo Code.
See change as an invitation to let go of attachments and embrace flow.top gun leather jacket
Uncovers the hidden symmetries that link theories from different realms.Kill Em With Comedy Hoodie
The tapestry of your writing is woven with intricate metaphors and analogies. Tom Cruise Top Gun Jacket
Possesses a rare capacity for extracting essential insights from convoluted theoretical constructs.<a href="https://cosplaystreet.com/collections/best-seller/products/top-gun-jacket>top gun maverick jacket original</a>
Your love for Stranger Things just got a cozy upgrade. Introducing the Stranger Things Puffer Jacket – designed for fans who know that adventure and style go hand in hand. Secure yours before they vanish like demogorgons.
Exploring GMock alongside Grails' mockDomain is like finding a solution as satisfying as learning "how to cancel regal unlimited." Your blog provides valuable insights on this combination, enhancing our understanding.
Implementing GMock alongside Grails' mockDomain is a strategic move that adds a powerful layer to your testing strategy. franklin graham home value The combination allows for a more comprehensive and flexible testing environment in Grails applications.
Saima Group offers the Best investment plans 2024. Their completed projects in various places in Karachi demonstrate their dedication to delivering affordable homes in Karachi. Saima Group provides simple payment plans, making it easier for people to obtain their dream houses.
Beth Dutton pink handbag is a must-have for any fashion lover. Its vibrant color and classic design create a perfect blend of style and elegance.
Site: Exclusive beth dutton handbag
Elevate your style with the Ted Lasso jacket collection. These jackets are a blend of comfort, style, and fan-favorite designs.
buy ted lasso series
As technology continues to evolve, its impact on education can’t be denied or overlooked. From online classes to interactive learning platforms, technology is remodeling how students take up their academic challenges now. All this has given rise to my assignment help services online—and rightly so. Here, you’ll know how these services enhance the educational experience and contribute to student success today.
https://essaywritinghelp.co.uk/
Post a Comment