Assignment 3: Mocking, Code Smell, and Refactoring
Assignment Instructions
Prerequisites: To complete this assignment, you will need experience with mocking, code
smells, refactoring, and Test-Driven Development (TDD). Mocking was discussed and
demonstrated in Lecture 6 using an example (e.g., TwitterClient). Code smells and refactoring were discussed and demonstrated in Lectures 8 and 9. If you are still facing difficulties with
TDD, BrightSpace contains extensive materials on TDD. The following tools and libraries should
be installed on your machine and they should be working properly to complete this assignment:
Android Studio Dolphin — 2021.3.1
Git
JUnit
Mockito 3.4.0
Espresso 3.3.0
Assignment Repository: https://git.cs.dal.ca/courses/2022-fall/csci-3130/csci3130-fall2022-a3
Note: To access the assignment repository, you must log in to your GitLab account.
Assignment Deadline: Oct 28 2022 11:59 PM.
Expectations: A single PDF document with a naming structure of BannerID-CSCI3130-
A3.pdf should be submitted to Brightspace by the deadline.
Document format and naming structure are followed (01 mark).
Fork the assignment repository to your Dalhousie GitLab account. Then clone the forked
repository (under your GitLab account) to your local machine using Git. If this step is not
followed properly, 03 marks will be penalized.
Must change your repository permission to private (Must be done!) (01 mark).
Must add user prof3130 as a maintainer of your repository. Markers will use this account for
evaluation. They will not be able to mark the rest if you fail to invite prof3130 (01 mark).
Must add GitLab link of your forked repository to the answer PDF (01 mark).
Q1: Screenshot of the passing unit tests + Commits submitted to GitLab with appropriate
messages (10 marks)
Q2: Screenshot of the passing unit tests + Commit submitted to GitLab with an appropriate
message (08 marks)
Q3: Screenshot of the passing unit tests + Commit submitted to GitLab with an appropriate
message (08 marks)
Q4: Screenshot of the passing unit tests + Commit submitted to GitLab with an appropriate
message (05 marks)
Q5: Screenshot of the passing Espresso tests + Commit submitted to GitLab with an appropriate message (04 marks)
Fall 2022: CSCI 3130 - Introduction to Software Engineering Assignment 3 Page 1 of 4
Unless otherwise specified, test methods must not be modified in the assignment repository. Non-allowed modifications to test methods will lead to penalties.
Push all commits to the master branch of your forked GitLab repository (01 mark).
Total marks: 40
Questions
Q1 (10 marks): Let us consider that you have been developing an e-commerce application for an
ABC company. Online payment for purchased products is a required feature of any e-commerce application. To handle all online payments, you have created a business class namely PaymentManager.
Currently, the class takes IPayment as a parameter in its makePayment() method. Unfortunately,
makePayment() method is buggy and IPayment interface has not been implemented yet. However,
due to a client’s deadline, you still need to test PaymentManager class.
As you might remember, when the implementation of a class or an external dependency is
missing, we can mock them using a mocking framework called Mockito. Lecture 6 discussed and
demonstrated this framework. Please do the following.
Execute PaymentManagerTest and see the unit tests to fail.
Complete the implementation of convertToDate() method from PaymentManager class.
Make a separate commit with an appropriate message to GitLab (02 marks).
At this stage, ABC company will accept payments from only two major credit cards: Mastercard and Visa. A Mastercard number has 16 digits and begins with 5. On the other
hand, a Visa card number has 13 or 16 digits, and begins with 4. (More details about credit
cards can be found here). Complete the implementation of isSupportedCard() method
from PaymentManager class by checking both length and first digit of a card number. Make
a separate commit with an appropriate message to GitLab (02 marks).
Fix the buggy code in makePayment() method and make a separate commit with an appropriate message to GitLab (02 marks).
Use Mockito framework to mock IPayment interface: (a) initialize firstPayment, secondPayment,
and thirdPayment, (b) add mocked behaviours to them, and (c) then pass the failed tests
from PaymentManagerTest. You will need to mock all three methods from IPayment interface
to pass the failed tests. Once done, make a separate commit with an appropriate message to
GitLab and attach a screenshot of the passing tests to the answer PDF (04 marks).
Q2 (08 marks): Let us consider that your e-commerce application has three types of users -
sellers, buyers and administrator. A seller can place online ads for his/her products through your
application. A buyer can respond to these ads and place online orders. On the other hand, an
administrator can manage both the buyers and sellers, and can place both online ads and orders.
Once a user logs in, your application determines the user’s type and then provides appropriate
access levels (e.g., placing an ad or order). As a part of TDD, you and your partner already
implemented an ad-hoc version of access control mechanism in AppUser class. However, your
current implementation of AppUser contains a switch-case statement, which is considered to be
a code smell. Interestingly, switch-case statement can be replaced with polymorphism concept
from OOP and the current code can be improved through refactoring. This problem has been
extensively discussed in Lectures 8 and 9. Please do the following.
Fall 2022: CSCI 3130 - Introduction to Software Engineering Assignment 3 Page 2 of 4
Execute the tests from AppUserTest class and see the unit tests passing.
Refactor the production code by (a) converting AppUser class into an abstract class and (b)
creating three new classes – Seller, Buyer and Admin – that extend (a.k.a., inherit) the
abstract class and preserve its original behaviours. For example, a buyer should be allowed
to place online orders but not the ads. On the other hand, an admin should have exclusive
access to all available features (04 marks).
Modify the constructor in each test method from AppUserTest using appropriate classes
(e.g., for Seller, AppUser seller=new Seller();) and make sure that these tests are still
passing with your refactored code. Once done, make a separate commit with an appropriate
commit message to GitLab and attach a screenshot of the passing unit tests to the answer
PDF (04 marks).
Q3 (08 marks): In your course project, you have been dealing with at least one of these two items
– used goods (e.g., laptop, headphone) and small tasks (e.g., walk a dog, pickup my groceries). Let
us consider that you are developing another mobile application that can store both of these items.
Your application has an in-memory database called ItemManager. It stores and delivers three
types of entries – Item, UsedGoods, and SmallTask where both UsedGoods and SmallTask inherit
the behaviours of Item class. However, the current implementation contains refused bequest code
smell, which could lead to bugs in the future. Use two refactoring techniques – push down and
replace inheritance with delegates – to refactor the production code. All the unit tests from
ItemManagerTest are currently passing and they should also pass with the refactored production code. These code smell and refactoring techniques have been discussed and demonstrated in
Lectures 8 and 9. Please do the following.
Execute ItemManagerTest class and see all unit tests to pass except one.
Modify Item, UsedGoods, and SmallTask classes using push down refactoring technique,
override the inherited methods if necessary, and make sure that all unit tests are passing.
Once done, make a separate commit with an appropriate message to GitLab and attach a
screenshot of the passing tests to the answer PDF (05 marks)
Modify Transaction class using replace inheritance with delegates refactoring technique
and make sure that testGetTransactionAmount() is passing. Once done, make a separate
commit with an appropriate message to GitLab and attach a screenshot of the passing test
to the answer PDF (03 marks)
Q4 (05 marks): Let us consider that you have been designing an e-commerce application for
Atlantic Superstore. In your application, you are representing customers using Customer class, as
provided in the assignment repository. However, currently, the class handles multiple responsibilities rather than a single responsibility, which is a poor design choice. (Remember the single
responsibility principle). For example, several fields such as areaCode, pcCardNumber, and points
should not be an attribute of the Customer class. Refactor the production code by designing
another class namely PCCard and then using it as a delegate (or attribute) in the Customer class.
This refactoring technique has been discussed and demonstrated in Lecture 9. All the unit tests
from CustomerTest should pass with the refactored code. Please do the following.
Execute CustomerTest class and see the unit tests to pass.
Fall 2022: CSCI 3130 - Introduction to Software Engineering Assignment 3 Page 3 of 4
Refactor Customer class using move field and extract class refactoring techniques, replace
redundant fields with the delegate of a new class – PCCard, and make sure that the tests from
CustomerTest are still passing with the refactored code. Once done, make a separate commit
with an appropriate message to GitLab and attach a screenshot of the passing tests to the
answer PDF (05 marks)
Q5 (04 marks): Let us consider that you are working on a fun math project. Once the assignment
repository is built and deployed on an emulator, you will see one text box and two press buttons
– FACTORIAL and SQUARE. The text box accepts a number, and the buttons calculate the
factorial and square of the number. The design can be found in layout/activity main.xml file
and the business code can be found in the MainActivity class. However, the current business
code contains copy/pasted code (a.k.a., duplicate code) in several places, which can be refactored
using extract method refactoring technique. It was discussed in Lectures 8 and 9. At least two new
methods can be extracted from the current version of the duplicate code. Please do the following.
Execute ExampleInstrumentedTest and see the Espresso tests to pass.
Refactor the business code in MainActivity by removing duplicate code with extract method
technique, design two new methods, and invoke them from appropriate places within the
code. Make sure that the Espresso tests from ExampleInstrumentedTest are still passing
with the refactored code. Once done, make a separate commit with an appropriate message
to GitLab and attach a screenshot of the passing tests to the answer PDF (04 marks)
Version: October 13, 2022
Fall 2022: CSCI 3130 - Introduction to Software Engineering Assignment 3 Page 4 of 4