{"id":141,"date":"2009-06-01T18:44:04","date_gmt":"2009-06-02T01:44:04","guid":{"rendered":"http:\/\/www.connorgarvey.com\/blog\/?p=141"},"modified":"2010-02-12T09:07:47","modified_gmt":"2010-02-12T16:07:47","slug":"testing-in-android-with-mock-ui-components","status":"publish","type":"post","link":"https:\/\/connorgarvey.com\/blog\/?p=141","title":{"rendered":"Testing in Android with mock UI components"},"content":{"rendered":"<p>As <a href=\"http:\/\/www.connorgarvey.com\/blog\/?p=137\">described in an earlier post<\/a>, Android is not friendly to mocking frameworks or mock-style testing.\u00a0 If you want to test any class in your application that deals with the Android API, it&#8217;s best to run your tests through the emulator, accessing real Android classes.\u00a0 It&#8217;s unfortunate because you&#8217;re not just testing your application.\u00a0 You&#8217;re also testing Android.\u00a0 Anyway, here&#8217;s a way to mock a UI component.<\/p>\n<p>If you&#8217;re just starting, here are a couple notes to keep you on the right track.<\/p>\n<ul>\n<li>Android is bundled with JUnit 3.\u00a0 Don&#8217;t try using an updated JUnit library or another testing framework.\u00a0 The Android jar doesn&#8217;t contain any functional code, so all test cases have to be run in the emulator, which uses JUnit 3.\u00a0 The test framework that will work best is in the Android API.<\/li>\n<li>If you need basic implementations of Android classes, try to avoid mocking them.<\/li>\n<\/ul>\n<h3>&#8220;Mock&#8221;ing<\/h3>\n<p>In my latest test, I needed a TextView so that I could call the simplest method, setText(String).\u00a0 I&#8217;ll describe how I got one.<\/p>\n<p>Don&#8217;t bother with the android.test.mock package.\u00a0 It just contains implementations of classes that throw UnsupportedOperationExceptions.\u00a0 There isn&#8217;t anything there that I have yet found useful.<\/p>\n<ol>\n<li>In the test case, instead of extending TestCase, extend at InstrumentationTestCase or, if necessary, one of its subclasses.\u00a0 It&#8217;ll set up most of the stuff that&#8217;s available in an Activity and make it available to your test case.\n<div id=\"wpshdo_1\" class=\"wp-synhighlighter-outer\"><div id=\"wpshdt_1\" class=\"wp-synhighlighter-expanded\"><table border=\"0\" width=\"100%\"><tr><td align=\"left\" width=\"80%\"><a name=\"#codesyntax_1\"><\/a><a id=\"wpshat_1\" class=\"wp-synhighlighter-title\" href=\"#codesyntax_1\"  onClick=\"javascript:wpsh_toggleBlock(1)\" title=\"Click to show\/hide code block\">Code block<\/a><\/td><td align=\"right\"><a href=\"#codesyntax_1\" onClick=\"javascript:wpsh_code(1)\" title=\"Show code only\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/code.png\" \/><\/a>&nbsp;<a href=\"#codesyntax_1\" onClick=\"javascript:wpsh_print(1)\" title=\"Print code\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/printer.png\" \/><\/a>&nbsp;<a href=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/About.html\" target=\"_blank\" title=\"Show plugin information\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/info.gif\" \/><\/a>&nbsp;<\/td><\/tr><\/table><\/div><div id=\"wpshdi_1\" class=\"wp-synhighlighter-inner\" style=\"display: block;\"><pre class=\"java\" style=\"font-family:monospace;\"><span class=\"kw1\">public<\/span> <span class=\"kw1\">class<\/span> AnAndroidTest <span class=\"kw1\">extends<\/span> InstrumentationTestCase <span class=\"br0\">&#123;<\/span><\/pre><\/div><\/div>\n<\/li>\n<li>Create a mock implementation of TextView or the class you need.\n<div id=\"wpshdo_2\" class=\"wp-synhighlighter-outer\"><div id=\"wpshdt_2\" class=\"wp-synhighlighter-expanded\"><table border=\"0\" width=\"100%\"><tr><td align=\"left\" width=\"80%\"><a name=\"#codesyntax_2\"><\/a><a id=\"wpshat_2\" class=\"wp-synhighlighter-title\" href=\"#codesyntax_2\"  onClick=\"javascript:wpsh_toggleBlock(2)\" title=\"Click to show\/hide code block\">Code block<\/a><\/td><td align=\"right\"><a href=\"#codesyntax_2\" onClick=\"javascript:wpsh_code(2)\" title=\"Show code only\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/code.png\" \/><\/a>&nbsp;<a href=\"#codesyntax_2\" onClick=\"javascript:wpsh_print(2)\" title=\"Print code\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/printer.png\" \/><\/a>&nbsp;<a href=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/About.html\" target=\"_blank\" title=\"Show plugin information\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/info.gif\" \/><\/a>&nbsp;<\/td><\/tr><\/table><\/div><div id=\"wpshdi_2\" class=\"wp-synhighlighter-inner\" style=\"display: block;\"><pre class=\"java\" style=\"font-family:monospace;\"><span class=\"kw1\">public<\/span> <span class=\"kw1\">class<\/span> MockTextView <span class=\"kw1\">extends<\/span> TextView <span class=\"br0\">&#123;<\/span>\n\u00a0 <span class=\"kw1\">public<\/span> MockTextView<span class=\"br0\">&#40;<\/span><span class=\"kw1\">final<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Acontext+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky\"><span class=\"kw3\">Context<\/span><\/a> context<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n\u00a0\u00a0\u00a0 <span class=\"kw1\">super<\/span><span class=\"br0\">&#40;<\/span>context<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n\u00a0 <span class=\"br0\">&#125;<\/span>\n<span class=\"br0\">&#125;<\/span><\/pre><\/div><\/div>\n<\/li>\n<li>The TextView constructor needs a real Context object because it will call methods on it.\u00a0 The context is difficult to mock because parts of it are private to Android.\u00a0 Since the Android JAR is just an API and doesn&#8217;t have any functional code, you couldn&#8217;t even see the methods if you tried.\u00a0 They only exist in the VM in the emulator.\u00a0 AFAIK, if you can&#8217;t see a method, you can&#8217;t mock it.\u00a0 That&#8217;s why your test case extends InstrumentationTestCase.\u00a0 Put this in it.\n<div id=\"wpshdo_3\" class=\"wp-synhighlighter-outer\"><div id=\"wpshdt_3\" class=\"wp-synhighlighter-expanded\"><table border=\"0\" width=\"100%\"><tr><td align=\"left\" width=\"80%\"><a name=\"#codesyntax_3\"><\/a><a id=\"wpshat_3\" class=\"wp-synhighlighter-title\" href=\"#codesyntax_3\"  onClick=\"javascript:wpsh_toggleBlock(3)\" title=\"Click to show\/hide code block\">Code block<\/a><\/td><td align=\"right\"><a href=\"#codesyntax_3\" onClick=\"javascript:wpsh_code(3)\" title=\"Show code only\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/code.png\" \/><\/a>&nbsp;<a href=\"#codesyntax_3\" onClick=\"javascript:wpsh_print(3)\" title=\"Print code\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/printer.png\" \/><\/a>&nbsp;<a href=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/About.html\" target=\"_blank\" title=\"Show plugin information\"><img decoding=\"async\" border=\"0\" style=\"border: 0 none\" src=\"https:\/\/connorgarvey.com\/blog\/wp-content\/plugins\/wp-synhighlight\/themes\/default\/images\/info.gif\" \/><\/a>&nbsp;<\/td><\/tr><\/table><\/div><div id=\"wpshdi_3\" class=\"wp-synhighlighter-inner\" style=\"display: block;\"><pre class=\"java\" style=\"font-family:monospace;\"><span class=\"kw1\">final<\/span> TextView textView <span class=\"sy0\">=<\/span> <span class=\"kw1\">new<\/span> MockTextView<span class=\"br0\">&#40;<\/span><span class=\"kw1\">this<\/span>.<span class=\"me1\">getInstrumentation<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>.<span class=\"me1\">getContext<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><\/pre><\/div><\/div>\n<\/li>\n<\/ol>\n<p>Now write the test case.\u00a0 The text view is real and has a fully functional context, so the emulator will have everything it needs to support your test case.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As described in an earlier post, Android is not friendly to mocking frameworks or mock-style testing.\u00a0 If you want to test any class in your application that deals with the Android API, it&#8217;s best to run your tests through the emulator, accessing real Android classes.\u00a0 It&#8217;s unfortunate because you&#8217;re not just testing your application.\u00a0 You&#8217;re [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[57],"tags":[3,4,29,8,27,5,7,28],"class_list":["post-141","post","type-post","status-publish","format-standard","hentry","category-android","tag-android","tag-java","tag-junit","tag-mobile","tag-mocking","tag-programming","tag-redpoint","tag-test"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1ql2n-2h","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=141"}],"version-history":[{"count":6,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/141\/revisions"}],"predecessor-version":[{"id":143,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/141\/revisions\/143"}],"wp:attachment":[{"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=141"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=141"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/connorgarvey.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}